数据库
LIMIT分页优化
  • By刘立博
  • 2020-03-08 19:45:58
  • 723人已阅读

测试数据

本文使用MYSQL数据模板SAKILA,作为测试数据。

下载地址:https://downloads.mysql.com/docs/sakila-db.zip

 

大偏移量性能问题

但需要分页操作时,通常使用LIMIT+偏移量+order by的方式实现。如果使用了索引,效率通常是不错的。但是在偏移量非常大的时候,比如500000,10这样的查询,MYSQL需要查询出500010条结果,丢弃掉前500000条后返回10条,这样带来了极高的性能损耗

 

延迟关联

优化大偏移量的性能问题的基本思路是尽可能的使用覆盖索引查找到数据行的主键ID(聚簇索引)或内存地址指针(非聚簇索引)再读取指定数据行,这样可以大大的减少数据库IO开销

假定我们需要获取film表第91页的列表数据,其偏移量为900,10。以title(btree索引)排序:SQL如下:

 

直接按title排序,使用了文件排序,并扫描了全表

ID:2 首先使用二级索引title查找出所需的主键ID

ID:1 使用主键ID获取具体数据行(这里我原本期望ROWS为10,但显示的是910)

 

为了验证这个疑惑,我用一张数据较多的表进行了验证,此表数据量16W,其中crate_time字段为BTREE索引,主键为id,偏移量100000,10 结果如下:

普通偏移查询,耗时0.49秒

延迟关联查询,耗时0.2秒

预先计算边界值

缓解偏移量带来的消耗的另一种思路是预先计算出边界值,然后通过WHERE语句进行约束:

假定已知第91页ID偏移量为900,92页的偏移量为910,那么SQL语句可以这样写:

 

MYSQL优化器同时采取了从尾部扫描的方式对SQL作出了优化,91页扫描100行即可获取结果,92页只需要扫描90行

再使用大表进行验证

同样偏移100000,耗时0.11秒