我有一张有两三百万行的表......
mysql> select count(*) from tbl;
+----------+
| count(*) |
+----------+
| 2615889 |
+----------+
1 row in set (1.23 sec)
mysql> show indexes from tbl;
+-------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| tbl | 0 | PRIMARY | 1 | tbl_id | A | 2284627 | NULL | NULL | | BTREE | | |
| ...
| tbl | 1 | tbl_fld | 1 | fld | A | 2284627 | NULL | NULL | YES | BTREE | | |
+-------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
6 rows in set (0.30 sec)
...对于以下查询,如果我添加order by
子句,我似乎做得更好(即,最终使用索引)...
mysql> explain select * from tbl
-> where fld in (select fld from tbl group by fld having count(*)>1)
-> limit 1000;
+----+--------------------+-------+-------+---------------+---------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-------+-------+---------------+---------+---------+------+---------+-------------+
| 1 | PRIMARY | tbl | ALL | NULL | NULL | NULL | NULL | 2328333 | Using where |
| 2 | DEPENDENT SUBQUERY | tbl | index | NULL | tbl_fld | 15 | NULL | 1 | Using index |
+----+--------------------+-------+-------+---------------+---------+---------+------+---------+-------------+
2 rows in set (0.00 sec)
mysql> explain select * from tbl
-> where fld in (select fld from tbl group by fld having count(*)>1)
-> order by fld limit 1000;
+----+--------------------+-------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-------+-------+---------------+---------+---------+------+------+-------------+
| 1 | PRIMARY | tbl | index | NULL | tbl_fld | 15 | NULL | 1000 | Using where |
| 2 | DEPENDENT SUBQUERY | tbl | index | NULL | tbl_fld | 15 | NULL | 1 | Using index |
+----+--------------------+-------+-------+---------------+---------+---------+------+------+-------------+
2 rows in set (0.00 sec)
......为什么会这样?
答案 0 :(得分:0)
从快速浏览一下,看起来它在第二个查询中使用了一个键是一件好事,因此它会阻止对表进行全面扫描。
答案 1 :(得分:0)
如果没有ORDER BY,则不应使用LIMIT,因为它没有明确定义将返回哪些行。正如您发现ORDER BY .. LIMIT optimization不起作用(并未在所有AFAIK上实现),而当您添加ORDER BY时,优化开始,并且在找到足够的行后MySQL停止执行。