另外此bug引发的另一个问题是,由于使用了LIMIT语句,导致选择的INDEX不是最优的INDEX。
SET optimizer_trace="enabled=on";
执行上面的查询语句,可以看到optimizer trace的输出结果如下,请注意里面重点部位的注释(以’//’开头部分):
make_join_select函数中有下面一段逻辑:
if (!tab->const_keys.is_clear_all() && // 有依赖于常量的索引条件表达式
i == join->const_tables && // 是第一个非常量表
(join->unit->select_limit_cnt <
tab->position->records_read) &&
!(join->select_options & OPTION_FOUND_ROWS)) // 没有SQL_CALC_FOUND_ROWS
...
// 检查是否有RANGE scan可以使用
if ((recheck_reason != DONT_RECHECK) &&
sel->test_quick_select(thd, usable_keys,
used_tables & ~tab->table->map,
(join->select_options &
join->unit->select_limit_cnt),
false, // don't force quick range
interesting_order) < 0)
{
这里usable_keys是描述可以用来对ORDER BY列进行索引排序的可能的所有索引的MAP。上面的函数会查找这些可用的索引是否可以进行更高效RANGE
扫描。但是通过问题query的条件表达式,这里没有找到对应的RANGE扫描,所以最后的执行计划输出只是使用了一个COVERING index.
可以看到最终效果是:
EXPLAIN SELECT id FROM t1 WHERE a<3 AND b IN (1, 13) AND c>=3 ORDER BY c DESC LIMIT 2;
1 SIMPLE t1 range iabc,ic iabc 5 NULL 4 Using index condition; Using filesort