1、 现象
a.只查询主键列的时候走某个索引
b.带上业务需要的其他字段的时候mysql选择走主键
走索引会比较高效,需要确认为什么走到了主键
2、 原因分析
查看optimizer_trace,发现两种SQL,cost评估都是正常的,但在最后order by上换到主键了
发现相关优化器BUG,官方BUG#97001
5.7.33增加了优化器开关prefer_ordering_index,来禁用order by、limit的优化;参考:github.com/mysql/mysql-server/commit/f4d5197f860df66234d0f580cae2e18a5cfeadb6
3、 解决方案
临时方案: 改写SQL,去掉order by 避免优化器走到primary主键;
长期方案: 内核版本升级至5.7.33及以上,prefer_ordering_index=off禁用优化;
4、 补充8.0相关bug
官方BUG#100257
8.0类似问题,官方建议:optimizer_switch='block_nested_loop=off'
5、最终建议
order by xx limit N的语法,在5.7、8.0两个版本中均具备缺陷,即使提供了优化器参数的方案,但block_nested_loop=off可能会导致其他SQL无法得到最优性能表现;8.0版本中block_nested_loop=off即等于放弃了hash join的特性。
因此建议:
1、不调整optimizer_switch参数,保持block_nested_loop=on默认值;
2、业务开发尽量避免使用order by xx limit N的SQL;