一.用法

在Mysql中分页查询使用关键字limit。limit的语法如下:

SELECT * FROM tbl LIMIT 5,10; # Retrieve rows 6-15

limit关键字带有两个参数,第一个参数表示相对于第一行的偏移量,第二个参数表示检索出的最大行数。初始化行数的偏移量是0而非1。

同行分页中会根据页码和每页条数计算出limit的偏移量即第一个参数,每页大小即第二个参数,开完成分页查询。

SELECT * FROM tbl LIMIT 5; # Retrieve first 5 rows

如果只有一个参数,表示从偏移量0处开始,返回5行,即:

SELECT * FROM tbl LIMIT 0, 5; # Retrieve first 5 rows

limit工作原理:如以上的limit 5,10,mysql会从偏移量0开始查询出15条,舍弃前面的5条,返回后面的10条。所以limit的工作方式是,查询出(偏移量 + 返回条数)条数据,然后舍弃前面的返回后面的所需条数。

二.问题

使用limit的过程中可能会发生的问题:

问题1. 分页查询性能问题

正如上面的limit的工作原理阐述,如果大数据表中limit分页查询或者查询指定偏移量后的数据,随着偏移量的逐渐增大,limit的性能越来越差,甚至赶上全表扫描。比如为1000w,那么mysql会将偏移的1000w条全部查询出来,这样就极大的影响性能。

注:limit对于返回指定条数的性能极好,从偏移量0出开始,取出指定条数返回即可。

问题2. 查询结果不一致

当order by和limit同时使用时,在order by排序字段上,有重复字段时,会出现相同查询语句的查询结果可能不一致。

官方文档时这样描述:

If multiple rows have identical values in the ORDER BY columns, the server is free to return those rows in any order, and may do so differently depending on the overall execution plan. In other words, the sort order of those rows is nondeterministic with respect to the nonordered columns.

有多行在order by排序字段上具有相同值,可能会按照任意顺序自由返回这些行。换句话说,这些具有相同值的行的顺序具有不确定性。

这时如果再使用limit分页,可能在不同页返回相同行的数据。因为那些相同值的列在每次查询的排序中具有不确定性,第n次排序分页查询出现,依然再下一次的排序分页查询中继续出现。

三.优化

1.分页查询性能优化

分析:

是因为分页时,随着偏移量的增大会造成将偏移量之前的数据也查询一遍导致。

解决方式:

  • 解决方式一:限制查询分页的页码,比如最多只能查询100页。后面的数据属于历史过久的数据,不予展示。简单粗暴,在一些特定场景中可以使用。

  • 解决方式二:上面分析了limit性能差的原因是因为将偏移量的之前的所有数据都查询了一遍——大海捞针,那么如果能让查询从少量数据开始查询那不就ok了——水杯捞针。既然要缩小查询范围,那么就必须过滤,既然过滤,那就必须where。使用了where最好再加上索引,那就更快了。
    经过分析,现在最为关键的是where的条件是什么。当然最好的是属于主键了,不过这个得看应用场景。那么每次分页的时候,where条件的值该怎么办?
    第一:可以将上次分页的结果作为下次分页的条件,这种情况时需要根据条件列进行排序,否则会出现重复结果,order by加上limit又会引发上述问题,可以参照解决。建议使用不重复列——主键、唯一索引列。如:where condition > condition_value order by condition limit 24;
    第二:如果id是连续自增不间断,可以根据页码和页数直接计算出条件,比如:where id > 20 * 24 limit 24;

  • 解决方式三:分析limit查询随着偏移量大时,需要查询前面的所有行,每行数据列非常多,所以导致慢。如果查询前面的行数据非常小,那是不是就快一点。基于此,可以先分页查询出主键,然后再根据主键关联,查询出所需行的全部数据。即使用子查询:select * from table id in (select id from table limit 300000, 10);
    但是这种方式也不会快很多,毕竟还是扫描了前面的全id。

  • 解决方式四:如果只是分页查询某个列,可以使用覆盖索引。针对该列建立索引,然后分页时只扫描整个索引便能获取数据,这样就不用扫描表行,加快分页速度。

2.结果不一致优化

分析:

是因为order by对相同值的排序具有不确定性导致,如果需要结果这个,要么让mysql支持对于前后查询都是一样的顺序,这样就会造成查询上下文了,mysql肯定不会这样设计。要么让排序的依据能够唯一,即排序的值是唯一的。

解决方式:

  • 解决方式一:选择具有唯一值的列进行排序

  • 解决方式二:多列值组合时唯一的情况下,选择多列上排序

四.Mysql对limit的优化

  • 在查询少量的行时,mysql有时使用索引,更多情况会全表扫描;

  • 在order by和limit混合使用时,mysql查询到排序结果中第一个limit的行数即结束,不会再排序所有的结果;

  • 在distinct和limit混合使用时,mysql查询到第一个唯一的limit行数时即返回;

参考

LIMIT Query Optimization
mysql 大数据量分页优化

Mysql系列(五)—— 分页查询及问题优化的更多相关文章

  1. MySQL大数据量分页查询方法及其优化

    MySQL大数据量分页查询方法及其优化   ---方法1: 直接使用数据库提供的SQL语句---语句样式: MySQL中,可用如下方法: SELECT * FROM 表名称 LIMIT M,N---适 ...

  2. MySQL分页查询的性能优化

    MySQL limit分页查询的性能优化 Mysql的分页查询十分简单,但是当数据量大的时候一般的分页就吃不消了. 传统分页查询:SELECT c1,c2,cn… FROM table LIMIT n ...

  3. 分页查询信息(使用jdbc连接mysql数据库实现分页查询任务)

             分页查询信息       使用jdbc连接mysql数据库实现分页查询任务 通过mysql数据库提供的分页机制,实现商品信息的分页查询功能,将查询到的信息显示到jsp页面上. 本项目 ...

  4. 【1】MySQL大数据量分页查询方法及其优化

    ---方法1: 直接使用数据库提供的SQL语句---语句样式: MySQL中,可用如下方法: SELECT * FROM 表名称 LIMIT M,N---适应场景: 适用于数据量较少的情况(元组百/千 ...

  5. MySQL 百万级数据量分页查询方法及其优化

    方法1: 直接使用数据库提供的SQL语句 语句样式: MySQL中,可用如下方法: SELECT * FROM 表名称 LIMIT M,N 适应场景: 适用于数据量较少的情况(元组百/千级) 原因/缺 ...

  6. 高性能MySql进化论(十一):常见查询语句的优化

    总结一下常见查询语句的优化方式 1        COUNT 1.       COUNT的作用 ·        COUNT(table.filed)统计的该字段非空值的记录行数 ·         ...

  7. Mysql系列五:数据库分库分表中间件mycat的安装和mycat配置详解

    一.mycat的安装 环境准备:准备一台虚拟机192.168.152.128 1. 下载mycat cd /softwarewget http:-linux.tar.gz 2. 解压mycat tar ...

  8. 如何选择普通索引和唯一索引《死磕MySQL系列 五》

    系列文章 一.原来一条select语句在MySQL是这样执行的<死磕MySQL系列 一> 二.一生挚友redo log.binlog<死磕MySQL系列 二> 三.MySQL强 ...

  9. mysql和oracle 分页查询(转)

    最近简单的对oracle,mysql,sqlserver2005的数据分页查询作了研究,把各自的查询的语句贴出来供大家学习..... (一). mysql的分页查询 mysql的分页查询是最简单的,借 ...

随机推荐

  1. python部分笔记

    创建类和对象 图片转在自:https://www.cnblogs.com/aylin/p/5547558.html 图片转在自:https://www.cnblogs.com/aylin/p/5547 ...

  2. tcp_tw_recycle参数引发的数据库连接异常

    [问题描述] 开发反馈有个应用在后端数据库某次计划性重启后经常会出现数据库连接异常问题,通过监控系统的埋点数据,发现应用连接数据库异常有两类表现:   其一:连接超时   131148.00ms To ...

  3. bat脚本输出日志

    一,bat脚本常用的的输出命令是“echo 输出内容”,可以利用echo将文本输出到cmd窗口或文件.bat脚本是不区分大小写的脚本语言,因此大小写都可以. 例如: REM 在命令行窗口输出 echo ...

  4. [TCP/IP] ping traceroute和TTL

    1.Time To Live是生存时间的意思,就是说这个ping的数据包能在网络上存在多少时间.当我们对网络上的主机进行ping操作的时候,我们本地机器会发出一个数据包,数据包经过一定数量的路由器传送 ...

  5. Centos7部署分布式文件存储(Fastdfs)

    目录 FastDFS介绍 楼主目标:前可H5撩妹,后可Linux搞运维 环境:Centos7 软件: 软件链接: 安装前所有准备,上传软件到Centos7上的/opt的目录下 安装依赖软件和类库(安装 ...

  6. 003-OpenStack-镜像服务

    OpenStack-镜像服务 [基于此文章的环境]点我快速打开文章 1.安装和配置 控制节点(controller) 1.1 创库授权 glance mysql CREATE DATABASE gla ...

  7. Paxos算法—前世

    Paxos算法是基于消息传递且具有高度容错特性的一致性算法.我们将从一个简单的问题开始,逐步的改进我们的设计方案,最终得到Paxos,一个可以在逆境下工作的协议. 一.客户端-服务器模型 我们从最小的 ...

  8. c# 第四节 Net Framework编写应用程序的过程

    本节 1:创建.net应用程序所经历的步骤 2:cli是什么 3:程序集是什么 4:jit编辑器 5:托管代码 1:创建.net应用程序所经历的步骤 2:cli是什么 3:程序集是什么 4:jit编辑 ...

  9. centos用手机号无法登入安全狗的解决方法

    前面我们安装好了安全狗,需要加服务器加入服云中,通常用sdcloud –u 用户名就可以,但如果是手机号的话就可能无法登陆,我们用sdcloud -h命令查看帮助,如下图所示 我们看到输入账号可以用- ...

  10. 如何确保redis中都是热数据

    相关知识:redis 内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略. redis 提供 6种数据淘汰策略: voltile-lru:从已设置过期时间的数据集(server.db[i].ex ...