问题描述:数据表有3000万行,单表分页查询,count时间在10s内,limit查询需要一分钟左右;表的索引非常多,几乎每写一个sql都会创建对应的索引,

sql类似:



select [data] from [table] where [condition] order by [sort] limit ?


尽管数据量很大,但也很慢的离谱了。查阅资料加上自己的尝试,发现sql慢的原因是mysql优化器默认选择了sort字段的索引,这个字段是个时间戳,区分度比较小,所以查询就会很慢。

跟业务沟通,他们坚持不允许修改排序的字段。好吧,那只能尝试改别的了。

第一种改法:给sql增加建议索引。一般情况下,加了建议索引,mysql就会走建议的索引,而不是自己去选择。



select [data] from [table] use index(idx) where [condition] order by [sort] limit ?


当然也可以强制sql走建议的索引:




select [data] from [table] force index(idx) where [condition] order by [sort] limit ?


确实有效的加快了查询速度。

但没过几天,又有一家客户反馈慢,经常,也是选择了慢的单字段的索引。出于其他客户的查询并不慢的考虑,只想给出问题的客户查询sql中指定索引,避免其他新的问题出现,但一家又一家也不是办法啊。。。

第二种改法:



select [data] from [table] ignore index(idx) where [condition] order by [sort] limit ?


既然这个sort索引非常慢,那我们将这个慢索引删除掉,mysql不就只能选择其他索引了么。。尝试去删除索引,在阿里云安全执行的加持下,删了半个小时,还是失败了。。体量太大,已经不允许增加索引或删除索引了。

又想到,既然可以建议索引,那也应该可以禁止索引吧?

确实可以禁用索引,ignore index().禁止了慢的索引,跟删除了索引是一个效果。加上一劳永逸

结论:

建索引的时候一定要慎重,区分度不大的字段不要建单索引,sql每次执行的时候只能走一个索引,不要给他太多选择。。选择题总会出错的