<返回更多

mysql优化实战:千万级数据表如何进行分页查询?

2019-10-11    
加入收藏

上次在MySQL8上导入一个1000万数据之后,今天就想验证看看mysql对于单表大数据的分页的表现情况,并探讨一下单表大数据分页的优化思路。

mysql优化实战:千万级数据表如何进行分页查询?

 


测试环境

简单说明下测试环境。

mysql优化实战:千万级数据表如何进行分页查询?

 

传统的分页查询

一般开发人员对于web分页的解决方案是使用limit子句来完成,语法为:

limit n,m

对于小规模数据应用来讲,可能并不会有大问题,在一定程度上还是比较有效率的,但是如果在大数据应用来讲,它的效率就可能很低了,因为它是全表扫描,数据越往后,即ID越大,数据越慢,例如下面的例子

select * from t_user LIMIT 90000 ,100 ##耗时 1秒
select * from t_user LIMIT 900000 ,100 ##耗时 2秒
select * from t_user LIMIT 9000000 ,100 ##耗时 6秒

耗时依次增加。

因为我们字段比较少,所以可能执行起来没想象中的慢,我们可以用执行计划来验证一下

explain select * from t_user LIMIT 1000000 ,100
mysql优化实战:千万级数据表如何进行分页查询?

 

从结果看出执行全表扫描,所以如果只取前面几条,则还是比较容易,如果是取相对靠后的数据,则全表扫描对数据库压力时非常大,特别web应用并发查询,则很容易造成数据库响应慢。

优化思路1

很明显,既然做全表扫描引起效率低下,那么我们第一印象肯定想办法是不是不走全表扫描。可以这么做,先在索引ID上完成分页操作,然后再根据ID关联回去。查询代码更新如下:

1.索引ID完成分页

select id from t_user order by id limit 9000000,100

2.最后完成自关联,最终SQL如下:

select * from t_user a inner join (select id from t_user order by id limit 9000000,100) b on a.id = b.id

3.看看执行计划,可见已经没有再全表扫描,这种方式是减少扫描来提高分页效率。

最终执行时间为3秒,效率提高一倍。

mysql优化实战:千万级数据表如何进行分页查询?

 

优化思路2

使用子查询进行优化,原理是通过子句先定位查询起始ID值,然后再通过主查询语句的ID往后查询,此方法适用ID排序的情况。举例如下:

select * from t_user where 
id>=(select id from t_user limit 9000000,1) 
limit 100;

通过执行计划查看,它也属于非全表扫描,所以效率同第一种优化方案

mysql优化实战:千万级数据表如何进行分页查询?

 

优化思路3

把LIMIT 查询转换成某个位置的查询,此思路需要和应用开发进行结合,不是单纯的数据库优化,因为我们实现的是web的分页查询,所以是可以通过页面的现实记录数和当前页,计算出该页的ID范围,我们拼出以下SQL

select * from t_user where id between 9000000 and 9000100 limit 100;

耗时只需0.4豪秒,是非常快速的查询,也是我们在生产中最常见的一种实现方法。

mysql优化实战:千万级数据表如何进行分页查询?

 

总结

优化方案2和优化3其实都是把LIMIT m,n转换成 limit n的查询,适合排序字段唯一的情况,当然大部分场景我们的排序字段都会选主键ID,这样操作的确能减轻分页的压力。理论上,几千万数据在mysql8上还是可以支撑的。

如果在数据量更大的情况下,这几种方案都无法满足了,一般我们得在数据库层和应用层之间设置缓存数据库,再执行分页查询。

声明:本站部分内容来自互联网,如有版权侵犯或其他问题请与我们联系,我们将立即删除或处理。
▍相关推荐
更多资讯 >>>