Mysql 不使用包含两列的索引

Posted

技术标签:

【中文标题】Mysql 不使用包含两列的索引【英文标题】:Mysql not using an index on where in with two columns 【发布时间】:2014-05-04 01:13:23 【问题描述】:

我有以下疑问:

select * from my_table 
where (col1, col2) in ( (1000,1), (2000,2) )

我在 col1、col2 和 col1 和 col2 上一起定义了索引。如果我对其进行解释,我会看到 mysql 找不到要使用的可用索引。有趣的是,如果我在 IN 子句中只放一对,解释会找到所有索引。

试力指数,无济于事

任何想法,我怎样才能让mysql识别索引?

【问题讨论】:

将实际的表/索引定义发布到问题本身中。 【参考方案1】:

您需要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)

【讨论】:

这是正确的方法,但由于我无法升级版本,我设法通过仅在其中一列上添加 where in 的解决方法来解决这个问题......详情见我的回答。【参考方案2】:

我设法在不升级 mysql 版本的情况下解决了这个问题,方法是仅在其中一列上添加额外的 where in 条件:

select * from my_table 
where (col1, col2) in ( (1000,1), (2000,2) )
and col1 in (1000,2000)

这样,优化器将在 col1 上找到索引,并按它进行搜索,这对我来说已经完成了这项工作。

【讨论】:

【参考方案3】:

我不知道这一点;所以首先尝试(小提琴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/优化请求的人已在此处解释(或)给出的复制步骤

Multi-Column IN clause – Unexpected MySQL Issue

【讨论】:

以上是关于Mysql 不使用包含两列的索引的主要内容,如果未能解决你的问题,请参考以下文章

两列的唯一索引加上每一列的单独索引?

使用pandas创建稀疏矩阵,并使用来自.dat文件的其他两列的索引[x,y]的.dat文件的一列中的值填充它

MySQL索引引擎

MySQL联合索引生效的条件、索引失效的条件

为啥索引不用于某些值?

mysql 全文模糊搜索MATCH AGAINST方法