mysql order by 在索引项存在varchar且被where限定常量时出现filesort分析

1.背景

由于一个业务表越来越大,大概有550万。突然某天出现了慢查询13s+,排查下来,发现是因为order by 没有走索引,为什么,以及如何处理,请看接下来的分析

1.1 表结构

CREATE  TABLE  `test` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT  'row id',
`content_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT  'contentID',
`type` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`province` varchar(100) CHARACTER SET utf8 NOT  NULL  DEFAULT  ''  COMMENT  '地区',
`time_created` bigint(20) NOT NULL DEFAULT '0' COMMENT  '创建时间',
PRIMARY KEY (`id`),
KEY `idx_province_type_time_created_content_id` (`province`,`type`,`time_created`,`content_id`)
) ENGINE =InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='test表'

1.2 sql语句

SELECT
	content_id,
	time_created 
FROM
	test 
WHERE
	province = 'shanghai' 
	AND type = 'aa' 
	AND time_created > 12345 
ORDER BY
	province,
	type,
	time_created 
	LIMIT 10

1.3 mysql版本

5.6

2 分析

拿到有问题的语句,首先explain一把

idselect_typetablepartitionstypepossible_keyskeykey_lenrefrowsfilteredExtra
1SIMPLEtestindexidx_province_type_time_created_content_ididx_province_type_time_created_content_id5201100Using where; Using index; Using filesort

可以看到由于排序没有走索引,进行了filesort

filesort:
If an index cannot be used to satisfy an ORDER BY clause, MySQL
performs a filesort operation that reads table rows and sorts them. A
filesort constitutes an extra sorting phase in query execution.

尝试修改语句,删除掉order by的常量项后,发现

SELECT
	content_id,
	time_created 
FROM
	test 
WHERE
	province = 'shanghai' 
	AND type = 'aa' 
	AND time_created > 12345 
ORDER BY
	type,
	time_created 
	LIMIT 10
idselect_typetablepartitionstypepossible_keyskeykey_lenrefrowsfilteredExtra
1SIMPLEtestindexidx_province_type_time_created_content_ididx_province_type_time_created_content_id5201100Using where; Using index

竟然走索引了,这是为啥呢,求助强大的google
搜到一个17年有人提出的bug
https://bugs.mysql.com/bug.php?id=88127
image.png

于是怀疑,是否就是编码的问题,请看下面的测试结果

3 测试

image.png

4 结论

从测试结果,可以看出在以下条件下,会导致order by不走索引

  • 1.character_set_connection = utf8mb4
  • 2.order by 索引有常数项,且 Collation =utf8mb4_unicode_ci
    经过优化查询时间由13090ms降为5ms
    经测试。该问题在最新版mysql中依然存在
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

huihttp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值