mysql IN子句不使用可能的键

Posted

技术标签:

【中文标题】mysql IN子句不使用可能的键【英文标题】:mysql IN clause not using possible keys 【发布时间】:2013-01-22 18:42:41 【问题描述】:

我有一个相当简单的 mysql 查询,其中包含一些内部连接,然后是 where 子句。我已经为连接中使用的所有列以及主键创建了索引。我还有一个包含 IN 运算符的 where 子句。当只有 5 个或更少的 id 被传递到 IN 子句时,查询优化器使用我的索引之一在合理的时间内运行查询。当我使用解释时,我看到类型是范围,键是 PRIMARY。我的问题是,如果我在 IN 子句中使用超过 5 个 id,优化器会忽略所有可用的索引并且查询运行速度非常慢。当我使用解释时,我看到类型是 ALL,键是 NULL。

有人可以解释一下这里发生了什么以及我该如何解决这个问题。

谢谢

【问题讨论】:

你能展示你到目前为止尝试过的东西吗=)可能是你的表模式和查询.. 当您使用多个 OR 语句而不是 IN 时,是否也会发生这种情况? @Mt.Schneiders 是的!当我用 OR 替换 IN 时,它的行为完全相同。 很奇怪。什么是表引擎? MyISAM 还是 InnoDB?此外,您是否尝试过“ANALIZE TABLE”命令? 【参考方案1】:

不管表上的“主键”索引如何优化 JOIN,您还应该有一个基于您应用 WHERE 的通用标准的索引。您的查询列需要更多信息,但您也应该对 WHERE 条件有一个索引。

【讨论】:

【参考方案2】:

您也可以尝试使用 Mysql 索引提示。它允许您指定在查询执行期间应使用哪个索引。

例子:

 SELECT * FROM table1 USE INDEX (col1_index,col2_index)
  WHERE col1=1 AND col2=2 AND col3=3;

-

SELECT * FROM table1 IGNORE INDEX (col3_index)
  WHERE col1=1 AND col2=2 AND col3=3;

更多信息在这里: Mysql Index Hints

【讨论】:

【参考方案3】:

在检查我遇到的类似问题时发现了这一点。认为我的发现可能会对将来遇到类似问题的其他人有所帮助。

我有一个大约 30 行的 MyISAM 表(包含类似单词的常见拼写错误,用于搜索,其中可能的原始拼写错误和替代单词都可能是有效的拼写,表格的大小会慢慢增加)。然而,对我来说,截止日期是如果 IN 子句中有 4 个项目,则使用索引,但当 IN 子句中有 5 个项目时,索引将被忽略(注意我没有尝试过替代词,所以 IN 子句中的实际单个项目可能是一个因素)。与 OP 非常相似,但字数不同。

使用索引 不起作用,索引仍然会被忽略。 强制索引 确实有效,但我宁愿避免指定索引(以防有人删除索引)。

对于一些测试,我用额外的 1000 个随机唯一行填充了表,即使 IN 子句中有 80 个项目,查询也会使用相关索引。

因此,MySQL 似乎根据 IN 子句中的项目数与表中的行数相比来决定是否使用索引(但可能还有其他一些因素在起作用)。

【讨论】:

以上是关于mysql IN子句不使用可能的键的主要内容,如果未能解决你的问题,请参考以下文章

Mysql使用IN搜索包含每个IN子句单词的条目

MYSQL 不使用可能的键

MySql IN 子句,试图匹配元组的 IN 列表

为啥对三个表的联合 mysql 查询比在不可能的 where 子句上连接更快?

MySQL 不使用带有 WHERE IN 子句的索引?

在 mysql 查询中使用 force index 子句可能有啥缺点? [关闭]