MySQL:为什么IN子句中的第5个ID会大大改变查询计划?

Isr*_*eca 5 mysql sql indexing query-performance

鉴于以下两个问题:

查询#1

SELECT log.id
FROM log
WHERE user_id IN
      (188858, 188886, 189854, 203623, 204072)
      and type in (14, 15, 17)
ORDER BY log.id DESC
LIMIT 25 OFFSET 0;
Run Code Online (Sandbox Code Playgroud)

查询#2 - 4个ID而不是5

SELECT log.id
FROM log
WHERE user_id IN
      (188858, 188886, 189854, 203623)
      and type in (14, 15, 17)
ORDER BY log.id DESC
LIMIT 25 OFFSET 0;
Run Code Online (Sandbox Code Playgroud)

解释计划

-- Query #1
1   SIMPLE  log range   idx_user_id_and_log_id  idx_user_id_and_log_id  4       41280   Using index condition; Using where; Using filesort
-- Query #2
1   SIMPLE  log index   idx_user_id_and_log_id  PRIMARY                 4       53534   Using where
Run Code Online (Sandbox Code Playgroud)

为什么添加单个ID会使执行计划如此不同?我说的是毫秒到~1分钟的时间差.我认为它可能与eq_range_index_dive_limit参数有关,但无论如何它都低于10(默认值).我知道我可以强制使用索引而不是clustered index,但我想知道为什么MySQL决定这一点.

我应该试着明白吗?或者有时候不可能理解查询计划者的决定?

额外细节

  • 表大小:11GB
  • 行数:1.08亿
  • MySQL:5.6.7
  • 从IN子句中删除哪个ID无关紧要.
  • 指数: idx_user_id_and_log_id(user_id, id)

Yak*_* R. 0

JOIN 效率更高。

使用 IN 运算符的值创建临时表。然后在表“log”和临时值表之间建立 JOIN。

请参阅此答案 以获取更多信息。