因为in
查询不使用索引,所以mysql会扫描所有记录来查找行。
来自http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html
B-Tree 索引特征
B 树索引可用于使用 =、>、>=、<、<= 或 BETWEEN 运算符的表达式中的列比较。
没有IN
和
哈希索引特征
哈希索引与刚才讨论的有些不同:
它们仅用于使用 = 或 <=> 运算符的相等比较(但速度非常快)。它们不用于查找值范围的比较运算符,例如 <。
也没有IN
。
正如@tombom 提到的,foo IN ('bar', 'bla')
是 的缩写foo = 'bar' OR foo = 'bla'
,但是,我相信它们是不同的。于是我对一张有足够数据记录的表进行了测试,发现如下:
mysql> show columns from t_key;
+-------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+----------------+
| a | int(11) | NO | PRI | NULL | auto_increment |
| b | int(11) | YES | MUL | NULL | |
+-------+---------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
mysql> select count(a) from t_key;
+----------+
| count(a) |
+----------+
| 989901 |
+----------+
1 row in set (0.00 sec)
mysql> explain select a from t_key where a in (select max(a) from t_key);
+----+--------------------+-------+-------+---------------+---------+---------+------+--------+------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-------+-------+---------------+---------+---------+------+--------+------------------------------+
| 1 | PRIMARY | t_key | index | NULL | PRIMARY | 4 | NULL | 989901 | Using where; Using index |
| 2 | DEPENDENT SUBQUERY | NULL | NULL | NULL | NULL | NULL | NULL | NULL | Select tables optimized away |
+----+--------------------+-------+-------+---------------+---------+---------+------+--------+------------------------------+
2 rows in set (0.00 sec)
mysql> explain select a from t_key where a =(select max(a) from t_key);
+----+-------------+-------+-------+---------------+---------+---------+-------+------+------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+------------------------------+
| 1 | PRIMARY | t_key | const | PRIMARY | PRIMARY | 4 | const | 1 | Using index |
| 2 | SUBQUERY | NULL | NULL | NULL | NULL | NULL | NULL | NULL | Select tables optimized away |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+------------------------------+
2 rows in set (0.00 sec)
然后我尝试IN
使用静态序列进行查询,它像@tombom 提到的那样工作:
mysql> explain select a from t_key where a in (100,200);
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
| 1 | SIMPLE | t_key | range | PRIMARY | PRIMARY | 4 | NULL | 2 | Using where; Using index |
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
1 row in set (0.00 sec)
mysql> explain select a from t_key where a=100 or a=200;
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
| 1 | SIMPLE | t_key | range | PRIMARY | PRIMARY | 4 | NULL | 2 | Using where; Using index |
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
1 row in set (0.00 sec)
我不知道mysql是否会在可能的情况下将IN
查询转换为ORs
一个(例如,在查询之前知道序列),我没有找到相关文档,但explain
表明它确实在这种情况下扫描了表。