放弃函数,正确使用索引,我意外收获500工资

SQL herman 646浏览
公告:“业余草”微信公众号提供免费CSDN下载服务(只下Java资源),关注业余草微信公众号,添加作者微信:xttblog,发送下载链接帮助你免费下载!
本博客日IP超过1800,PV 2600 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog,之前的微信号好友位已满,备注:返现
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序
视频教程免费领

学习不是立竿见影的,而是潜移默化的。程序员的分水岭一般是在阅读源码,看书学习底层原理、底层实现机制上。我个人深有感触!

最近写了不少关于 MySQL 方面的知识,不知道大家喜欢不喜欢?如果感兴趣,我希望能找到一起学习的人!下面这本《高性能 MySQL》让我重新认识了自己的不足,我以前只是一个数据库小小白而已。

话说,最近我们有一个报表查询,随着线上数据了的大爆发,导致查询越来越越慢。Boss 说了好多次,我们技术团队都给延期了。原本以为 Boss 就忘了这件事了,谁知道今天 Boss 又在技术群里说到,说把报表这一块给我优化好,我给他加薪 500。

有谁和钱会过不去呢?我第一时间抢答,我来解决。于是我去看了相关代码,发现在统计查询的时候,Where 字段中用到了函数。SQL 简化如下所示:

select * from xttblog where month(create_time) = 5;

上面 SQL 中,create_time 是有索引的。

相信不少人看到这句 SQL,就会说:“索引上使用函数,不会走索引的”。但实际上,你用 explain 分析,却不是这样。这是因为我前面的文章写到的走索引和顺序扫描问题。

另外,在面试中,再延伸一下,为什么不会使用索引?你该怎么回答。

MySQL B+ tree 索引

这就要从根上来说 B+ 树的索引了。简化如上图所示,对日期字段的索引树抽象结构。现在来看,我们的索引上的日期是“2018-01-01”这样的类型,而 month(create_time) 计算出来的数值是月份,很明显和索引上的值差别很大。因此 MySQL 再执行时放弃了索引扫码,而是使用了顺序扫描。因此查询会很慢。

那么该如何优化这条 SQL 呢?很简单,上面不是按顺序扫描吗?我们让 MySQL 按索引扫描不就行了吗?所以,我们简单的改动一下 SQL,如下所示:

select * from xttblog where create_time >= '2019-05-01' AND create_time <= '2019-05-31';

你看,有时候思路也很重要。并且理解 MySQL 的底层原理也很重要。最后感谢 Boss 的助攻!

这个问题,另外还有很多种解决方法。比如,表中的数据该迁移的,可以归档到历史表中等。请不要把业务和技术选择限定的太死!

业余草公众号

最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加作者微信号1:xmtxtt(5000人已满),微信号2:xttblog(5000人已满),微信号3:codedq(超3800)。备注:“1”,添加博主微信拉你进微信群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作也可添加作者微信进行联系!

本文原文出处:业余草: » 放弃函数,正确使用索引,我意外收获500工资