我有一个带有复合主键的MySQL表:(id1,id2)。我想获得(id1,id2)在成对列表中的所有行,例如((1,2,2,(2,6),(1,6)))。当该对列表仅包含一个元素时,由于查询速度非常快,因此似乎使用了索引。当成对列表包含多个元素时,查询将非常缓慢:
mysql> SELECT id1, id2 FROM my_table WHERE (id1, id2) in ((1817279, 0));
+---------+--------+
| id1 | id2 |
+---------+--------+
| 1817279 | 0 |
+---------+--------+
1 row in set (0.00 sec)
mysql> SELECT id1, id2 FROM my_table WHERE (id1, id2) in ((1819781, 2));
+---------+--------+
| id1 | id2 |
+---------+--------+
| 1819781 | 2 |
+---------+--------+
1 row in set (0.00 sec)
mysql> SELECT id1, id2 FROM my_table WHERE (id1, id2) in ((1817279, 0), (1819781, 2));
+---------+--------+
| id1 | id2 |
+---------+--------+
| 1817279 | 0 |
| 1819781 | 2 |
+---------+--------+
2 rows in set (1 min 22.72 sec)
我尝试使用FORCE INDEX (PRIMARY)
失败。知道为什么MySQL无法使用索引吗?
这是我的MySQL版本:mysql Ver 14.14 Distrib 5.6.33, for debian-linux-gnu (x86_64) using EditLine wrapper
答案 0 :(得分:1)
“行构造器”直到5.7.3才进行优化。示例WHERE (id1, id2) = (11, 22)
。来自更新日志:2013-12-03 5.7.3
里程碑13-已添加或更改的功能:
优化器现在可以将范围扫描访问方法应用于 这种形式的查询:
选择...从t1位置(col_1,col_2)IN((('a','b'),('c','d' ));
以前,要使用范围扫描,必须进行查询 写为:
SELECT ...从t1哪里(col_1 ='a'和col_2 ='b')或(col_1 = 'c'AND col_2 ='d');
要使优化器使用范围扫描,查询必须满足以下条件 条件:
只能使用IN谓词,不能使用NOT IN。
在IN谓词的左侧,行构造器中可能仅存在列引用。
- IN谓词右侧的
IN谓词的右侧必须有多个行构造器。
Row构造函数必须仅包含运行时常量,这些常量可以是文字常量或局部常量 在执行期间绑定到常量的列引用。
适用查询的EXPLAIN输出将从全表或 索引扫描到范围扫描。通过检查 的值 Handler_read_first, Handler_read_key, 和 Handler_read_next 状态变量。