MySQL:在WHERE IN子句中使用复合键的查询非常慢

时间:2018-11-06 18:00:46

标签: mysql innodb

我有一个带有复合主键的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

1 个答案:

答案 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   状态变量。