使用IN条件的查询,它查询任然是使用range范围类型,
优点:
会优化在第二索引键上的查询。而这时between这些使用范围查找类型所无法做到的优化。
缺点:
in使用net算法,会对产生正确的结果的所有可能进行匹配,要是in条件要匹配的范围很大的话,这就会使查询变慢。
要在1000行的表中找到3使用in的话,也许会扫描两倍有余的rows。
-
mysql> FLUSH STATUS;
-
Query OK, 0 rows affected (0.00 sec)
-
-
mysql> SELECT sql_no_cache name FROM people WHERE age BETWEEN 18 AND 20 AND zip IN (12345,12346, 12347);
-
+----------------------------------+
-
| name |
-
+----------------------------------+
-
| ed4481336eb9adca222fd404fa15658e |
-
| 888ba838661aff00bbbce114a2a22423 |
-
+----------------------------------+
-
2 rows IN SET (0.39 sec)
-
-
mysql> SHOW STATUS LIKE "Handler%";
-
+----------------------------+-------+
-
| Variable_name | Value |
-
+----------------------------+-------+
-
| Handler_commit | 0 |
-
| Handler_delete | 0 |
-
| Handler_discover | 0 |
-
| Handler_prepare | 0 |
-
| Handler_read_first | 0 |
-
| Handler_read_key | 1 |
-
| Handler_read_next | 42250 |
-
| Handler_read_prev | 0 |
-
| Handler_read_rnd | 0 |
-
| Handler_read_rnd_next | 0 |
-
| Handler_rollback | 0 |
-
| Handler_savepoint | 0 |
-
| Handler_savepoint_rollback | 0 |
-
| Handler_update | 0 |
-
| Handler_write | 14 |
-
+----------------------------+-------+
-
15 rows IN SET (0.00 sec)
可以通过上面的方法查看到server的处理过程。
注意以下两个参数:
| Handler_read_key | 1 | --当值为1的时候表示使用了index range扫描索引。
| Handler_read_next |
42250 | --这个参数和上面的参数是相互联系的,表示在使用index range扫描中分析了多少行数据。
再次再来说一下union的优化;看一下与in相比union的用武之地:
-
mysql> EXPLAIN SELECT * FROM people WHERE age=18 ORDER BY last_online DESC LIMIT 10;
-
+----+-------------+--------+------+---------------+------+---------+-------+-------+-------------+
-
| id | select_type | TABLE | type | possible_keys | KEY | key_len | ref | rows | Extra |
-
+----+-------------+--------+------+---------------+------+---------+-------+-------+-------------+
-
| 1 | SIMPLE | people | ref | age | age | 1 | const | 12543 | USING WHERE |
-
+----+-------------+--------+------+---------------+------+---------+-------+-------+-------------+
-
1 row IN SET (0.00 sec)
-
-
mysql> EXPLAIN SELECT * FROM people WHERE age IN(18,19,20) ORDER BY last_online DESC LIMIT 10;
-
+----+-------------+--------+-------+---------------+------+---------+------+-------+-----------------------------+
-
| id | select_type | TABLE | type | possible_keys | KEY | key_len | ref | rows | Extra |
-
+----+-------------+--------+-------+---------------+------+---------+------+-------+-----------------------------+
-
| 1 | SIMPLE | people | range | age | age | 1 | NULL | 37915 | USING WHERE; USING filesort |
-
+----+-------------+--------+-------+---------------+------+---------+------+-------+-----------------------------+
-
1 row IN SET (0.00 sec)
当在使用了in clause的时候同时又使用了排序。
这就会让in去匹配任何一个有可能(匹配更多冗余的数据行)很明显这是不必要的。同时有使用了filesort,对这条SQL造成的效率极低。
这个时候可以尝试使用union来做到更好的处理,
EXPLAIN (SELECT *
FROM people
WHERE age=
18 ORDER BY last_online
DESC LIMIT 10) UNION
ALL (SELECT *
FROM people
WHERE age=
19 ORDER BY last_online
DESC LIMIT 10) UNION
ALL (SELECT *
FROM people
WHERE age=
20 ORDER BY last_online
DESC LIMIT 10) ORDER BY last_online
DESC LIMIT 10;
-
| id | select_type | TABLE | type | possible_keys | KEY | key_len | ref | rows | Extra |
-
+----+--------------+--------------+------+---------------+------+---------+-------+-------+----------------+
-
| 1 | PRIMARY | people | ref | age | age | 1 | const | 12543 | USING WHERE |
-
| 2 | UNION | people | ref | age | age | 1 | const | 12741 | USING WHERE |
-
| 3 | UNION | people | ref | age | age | 1 | const | 12631 | USING WHERE |
-
|NULL | UNION RESULT | 2,3> | ALL | NULL | NULL | NULL | NULL | NULL | USING filesort |
-
+----+--------------+--------------+------+---------------+------+---------+-------+-------+----------------+
-
4 rows IN SET (0.01 sec)
尽管使用了union的连接还是使用了filesort,但是这次filesort只是对每个union产生很小的结果集的排序,然后再对他们取集合,这样似乎比使用in产生的冗余扫描行,少了很多!
阅读(11800) | 评论(0) | 转发(0) |