MySQL超大分页优化

易小灯塔
2020-12-22 / 0 评论 / 663 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2020年12月22日,已超过1434天没有更新,若内容或图片失效,请留言反馈。

MySQL超大分页优化

 

在数据库开发过程中我们经常会使用分页,核心技术是使用用limit start, count分页语句进行数据的读取

MySQL分页起点越大查询速度越慢

 

直接用limit start, count分页语句,表示从第start条记录开始选择count条记录 :

select *  from product limit start,  count

当起始页较小时,查询没有性能问题,我们分别看下从10, 1000, 10000, 100000开始分页的执行时间(每页取20条)。

select * from product limit 10, 20    0.002秒
select * from product limit 1000, 20   0.011秒
select * from product limit 10000, 20   0.027秒
select * from product limit 100000, 20  0.057秒

我们已经看出随着起始记录的增加,时间也随着增大, 这说明分页语句limit跟起始页码是有很大关系的,那么我们把起始记录改为100w看下:

select * from product limit 1000000, 20  0.682秒

我们惊讶的发现MySQL在数据量大的情况下分页起点越大查询速度越慢,300万条起的查询速度已经需要1.368秒钟。这是为什么呢?因为limit 3000000,10的语法实际上是mysql扫描到前3000020条数据,之后丢弃前面的3000000行,这个步骤其实是浪费掉的。

select * from product limit 3000000, 20 1.368秒

从中我们也能总结出两件事情:

  • limit语句的查询时间与起始记录的位置成正比
  • mysql的limit语句是很方便,但是对记录很多的表并不适合直接使用。

 

二、 limit大分页问题的性能优化方法

 

(1)利用表的覆盖索引来加速分页查询

MySQL的查询完全命中索引的时候,称为覆盖索引,是非常快的。因为查询只需要在索引上进行查找,之后可以直接返回,而不用再回表拿数据。在我们的例子中,我们知道id字段是主键,自然就包含了默认的主键索引。现在让我们看看利用覆盖索引的查询效果如何。

select id from product limit 1000000, 20 0.2秒

那么如果我们也要查询所有列,如何优化?

优化的关键是要做到让MySQL每次只扫描20条记录,我们可以使用limit n,这样性能就没有问题,因为MySQL只扫描n行。我们可以先通过子查询先获取起始记录的id,然后根据Id拿数据:

select * from vote_record where id>=(select id from vote_record limit 1000000,1) limit 20;

 

(2)用上次分页的最大id优化

先找到上次分页的最大ID,然后利用id上的索引来查询,类似于:

select * from user where id>1000000 limit 100

 

 

0

评论 (0)

取消