我是如何把无索引的条件查询SQL优化了一百倍

1 篇文章 0 订阅
1 篇文章 0 订阅

今天工作中要对一个千万级数据量的表进行一个数据统计,但是作为筛选条件的字段并未加索引,于是测试代码的时候发现执行起来非常慢,平均在十秒左右,最后想了个办法进行了优化,大概优化到了零点一秒左右。

具体场景及方案如下:

1、

目的是查询一个文件信息表中的,某个时间之前的所有视频类型的文件的容量大小的总和(时间存储格式为时间戳),那么直接写sql的话,就是

select sum(size) from file_table where file_time < 1557330936 and file_type = 'video'

但是这样的问题是,where后面两个字段,都没有建立索引,数据量大的情况之下,查询非常慢,而本表的索引除了主键,只有另一个完全不相关的字段,而这次操作,也只是偶尔做的,不值得再建立一个索引,那么我开始思考,咋才能把已有的索引用上呢。

2、

首先确定,如果利用,一定只能利用自增的主键(BTREE索引),另一个完全不相关的字段在这个场景没用。

想办法把where后面的条件,转换为用主键字段查询,那就用到索引了。首先想到的方案为,(id为主键)

select id from file_table where file_time < 1557330936 order by id desc limit 1

这个sql的目的是查询出来满足时间要求的最后一条数据的主键id,然后只需查询id小于这个id的数据就可以了。这条语句虽然也用没建立索引的字段file_time查询出来,但是有limit 1限制,查到第一条就可以了,不需要进行全表扫描,所以我大胆推测,会快很多(然后我就被打脸了)。

然后

select sum(size) from file_table where id <= '刚刚查出来的主键id' and file_type = 'video'

验证效率,发现并没有变快,甚至更慢了,我排查了一下,发现是order by id desc使得前一条语句很慢,果然做事不能靠感觉,我试了下,如果不加倒序,那快的很,问题就出在倒序这一步。看来就算是索引字段,那么大的表,重新排一遍,也要比较长时间的。

3、

我开始想办法去掉倒序。其实我一开始都打算去找别的方式实现了,结果灵光一闪,想到,我可以查满足时间条件的下一条,也就是第一条不满足时间条件的id,这个和满足条件的最后一条,不就是挨着的数据嘛!而查不满足条件的,也就是某某时间之后的第一条数据,就不需要倒序了。sql如下:

select id from file_table where file_time > 1557330936 limit 1
select sum(size) from file_table where id < '刚刚查出来的主键id' and file_type = 'video'

在本地mysql测试修改后的效率大概是不使用索引的一百倍,刚刚又趁着大晚上,测试了一下用户环境的数据,要比本地慢一点,应该是因为加上了传输的时间,以及正式环境比我本地数据要更多些,不过总共加起来,不超过一秒,对于偶尔执行的sql来说,满足要求了。

4、总结

对于需要条件查询的大量数据,直接的条件又没有加索引的情况,可以思考这个条件,是否和其他的加了索引的字段有关联。本次情景中,两个条件之中的创建时间条件,刚好和主键id一样,都是顺序增加的,于是可以先利用没有索引的字段,查出来最后一条满足要求的数据,再用这条数据的带索引的字段,去查询所有满足条件的数据,以此减少避免在无索引情况下扫描全表

这个方式我觉得比较取巧,可能不算是sql语句本身的优化,但是很有效,更多的是一种解决问题的思路,以此记录,如果能刚好带给你帮助,那我的记录就更有价值了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值