我有以下查询:
select * from my_table
where (col1, col2) in ( (1000,1), (2000,2) )
我在col1,col2和col1以及col2上定义了索引。如果我对它进行解释,我发现mysql没有找到可用的索引。有趣的是,如果我只在IN子句中放入一对,则解释会找到所有索引。
试过力量指数,没有帮助
任何想法,我如何让mysql识别索引?
答案 0 :(得分:3)
您需要MySql版本5.7.3或更高版本
早期版本不实现行构造函数表达式的优化
请点击此链接了解详情:https://dev.mysql.com/doc/refman/5.7/en/range-optimization.html#row-constructor-range-optimization
8.2.1.3.4行构造函数表达式的范围优化
从MySQL 5.7.3开始,优化器能够将范围扫描访问方法应用于此表单的查询:
SELECT ... FROM t1 WHERE(col_1,col_2)IN((' a',' b'),(' c',' ; d');
以前,对于要使用的范围扫描,查询必须写为:
SELECT ... FROM t1 WHERE(col_1 =' a' AND col_2 =' b') 或(col_1 =' c' AND col_2 =' d');
注意:行构造函数是表单的表达式:
( value1, value2, ... ,valueN)
或ROW( val1, val2, ..., valN)
。
答案 1 :(得分:1)
我没有意识到这一点;所以首先尝试(小提琴http://sqlfiddle.com/#!2/f88bb/2),是的,这是正确的;对于多列IN子句,它使用full table scan
而不是使用可用的索引。
经过多次搜索后发现它是MySQL中的一个BUG,目标是在MySQL 6.x
中发布或修复。
请点击此处查看完整信息Multi column IN does not use index
现在,您可以将查询转换为使用单个IN子句,以便识别索引;像
select * from my_table
where col1 in ( 1000,2000) and col2 in (1,2)
创建BUG /优化请求的人已在此处解释(OR)给定的复制步骤
答案 2 :(得分:1)
我设法在不升级mysql版本的情况下解决了这个问题,只在其中一个列上添加了一个额外的where条件:
select * from my_table
where (col1, col2) in ( (1000,1), (2000,2) )
and col1 in (1000,2000)
这样,优化器会在col1上找到索引,并将按它搜索,这为我完成了工作。