博客
关于我
4种MySQL分页查询优化的方法,你知道几个?
阅读量:377 次
发布时间:2019-03-05

本文共 2056 字,大约阅读时间需要 6 分钟。

数据库分页查询优化实践指南

当需要从数据库查询的表有上万条记录时,一次性查询所有结果会变得非常缓慢,特别是在数据量持续增加的情况下,这时分页查询就显得尤为重要。数据库分页查询方法多种多样,每种方法都有其适用的场景和优化点。本文将简要介绍几种常见的分页查询优化方法,并通过实际测试结果进行对比分析。

准备工作

为了对下面的优化方法进行测试,我们基于现有表进行说明:

  • 表名:order_history
  • 描述:某个业务的订单历史表
  • 主要字段:unsigned int id,tinyint(4) int type
  • 字段情况:该表共有37个字段,不包含text等大型数据,最大为varchar(500),id字段为索引且递增。
  • 数据量:5709294
  • MySQL版本:5.7.16

如果需要自己测试,可以编写shell脚本等工具插入数据进行测试。

一般分页查询

一般的分页查询可以通过MySQL的LIMIT子句实现。LIMIT子句用于指定返回的记录数。需要注意以下几点:

  • 参数说明

    • 第一个参数指定第一个返回记录行的偏移量(默认为0)。
    • 第二个参数指定返回记录行的最大数目。
    • 如果只给定一个参数,则表示返回最多的记录行数目。
    • 第二个参数为-1时,表示检索从某个偏移量到记录集结束的所有记录。
    • 偏移量默认为0而非1。
  • 示例

    select * from orders_history where type=8 limit 1000,10;

    该语句将从orders_history表中查询第1000条数据之后的10条记录(即第1001条到第10010条)。

  • 默认排序:数据表中的记录默认使用主键(通常为id)排序,上述结果相当于:

    select * from orders_history where type=8 order by id limit 10000,10;
  • 测试结果

    • 1条记录:3072ms 3092ms 3002ms
    • 10条记录:3081ms 3077ms 3032ms
    • 100条记录:3118ms 3200ms 3128ms
    • 1000条记录:3412ms 3468ms 3394ms
    • 10000条记录:3749ms 3802ms 3696ms
  • 随着每次请求的记录数增加,查询时间呈线性增长。可以看到,当每次查询的记录数低于100时,查询时间基本没有差异。但随着记录数的增加,查询时间显著增加。

    子查询优化

    这种优化方式通过先定位偏移位置的id,然后再向后查询,适用于id递增的情况。具体语句如下:

  • 获取单条记录的id

    select id from orders_history where type=8 limit 100000,1;
  • 根据id查询后续记录

    select * from orders_history where type=8 and id > (select id from orders_history where type=8 limit 100000,1) limit 100;
  • 测试结果

    • 单条记录查询:3674ms
    • id查询:1315ms
    • 后续记录查询(100条):1327ms
    • 后续记录查询(1000条):3710ms
  • 可以看出,通过使用select id代替select *,查询速度提高了3倍。子查询相较于普通分页查询,能够显著提升查询效率。

    id限定优化

    这种优化方式假设数据表的id是连续递增的,可以通过计算查询的id范围来实现分页查询。具体语法如下:

  • 基于范围查询

    select * from orders_history where type=2 and id between 1000000 and 1000100 limit 100;
  • 另一种写法

    select * from orders_history where id >= 1000001 limit 100;
  • 使用in子句

    select * from orders_history where id in (select order_id from trade_2 where goods = 'pen') limit 100;
  • 这种优化方式的优势在于可以直接定位到需要查询的记录范围,特别适用于已知id范围的情况。需要注意的是,某些MySQL版本不支持在IN子句中使用LIMIT

    临时表优化

    这种优化方式虽然不属于传统的查询优化,但值得提及。对于使用id限定优化中的场景,特别是在数据缺失或历史数据处理时,可以考虑使用临时存储的表来记录分页的id,然后通过IN子句查询。这种方法在数据量较大时能显著提升传统分页查询的速度。

    关于数据表的id说明

    一般情况下,数据库表中会强制添加一个递增的id字段,使得分页查询更加便捷。对于像订单库这样的数据量庞大,建议采取分库分表策略,并使用分布式的高并发唯一id生成器来生成唯一标识。

    最后

    欢迎在评论区留言交流,如果觉得文章有价值,请记得点赞支持!

    转载地址:http://rlvg.baihongyu.com/

    你可能感兴趣的文章
    node模块化
    查看>>
    node环境下使用import引入外部文件出错
    查看>>
    node编译程序内存溢出
    查看>>
    Node读取并输出txt文件内容
    查看>>
    node防xss攻击插件
    查看>>
    noi 1996 登山
    查看>>
    noi 7827 质数的和与积
    查看>>
    NOI2010 海拔(平面图最大流)
    查看>>
    NOIp2005 过河
    查看>>
    NOIP2011T1 数字反转
    查看>>
    NOIP2014 提高组 Day2——寻找道路
    查看>>
    NOIp模拟赛二十九
    查看>>
    Nokia5233手机和我装的几个symbian V5手机软件
    查看>>
    Non-final field ‘code‘ in enum StateEnum‘
    查看>>
    none 和 host 网络的适用场景 - 每天5分钟玩转 Docker 容器技术(31)
    查看>>
    None还可以是函数定义可选参数的一个默认值,设置成默认值时实参在调用该函数时可以不输入与None绑定的元素...
    查看>>
    NOPI读取Excel
    查看>>
    NoSQL&MongoDB
    查看>>
    NoSQL介绍
    查看>>
    Notepad ++ 安装与配置教程(非常详细)从零基础入门到精通,看完这一篇就够了
    查看>>