博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
用会 MySQL LIMIT
阅读量:6371 次
发布时间:2019-06-23

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

hot3.png

本文首发于个人微信公众号《andqian》,期待你的关注!

前言

  前面写了《读懂MySQL执行计划》和《写会MySQL索引》后,今天我们来说说MySQL中另外一个比较重要的概念,就是 LIMIT 关键字。

LIMIT是什么?

  LIMIT的概念,其实大家应该都很清楚,在百度百科中是这样描述的:

LIMIT是一种数据语言,主要是用于查询之后要显示返回的前几条或者中间某几行数据。

这里着重需要注意的是: offset为开始角标,count代表数量,如下图所示:

640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1

                  (图片来源: mysqltutorial)

理解了这个概念之后,我们就能够知道下面这两个语句的意思了:

LIMIT 0,100; (A)

LIMIT 10,100; (B)

语句A代表的是 :  从起始角标为0的位置,往后获取100条记录。

语句B代表的是 :  从起始角标为10的位置,往后获取100条记录。

(别以为这很简单,在之前的面试过程中,就有很多童鞋搞混了,将语句B理解成了: 从起始角标为10的位置,获取90条数据呢。)

其实,LIMIT还有一个比较常用的简化写法,如下所示:

LIMIT 100;

这其实就是对上述A语句的简化,其意思代表的是: 从其实角标为0的位置,往后获取100条记录。只是将其实角标0省略掉了而已。正是因为这样的特性,有很多应用也直接使用LIMIT来进行分页操作。

提问时间

    上面我们介绍了,LIMIT的概念,也理清楚了LIMIT每个参数的含义,那现在就留一个问题:

  • 问: LIMIT 0,100与 LIMIT 100000,100的执行效率是一样吗? 一样为什么?不一样又为什么?

     

ps: 在Java面试时会经常问到哦。我之前就被问到过。

执行LIMIT发生了什么?

     我们都知道, LIMIT一般是跟在order by xx asc|desc语句后的,接下来我们就来看看下面这两个语句,一起来分析一下上述问题的答案:

语句A:

select * from t_base_user order by oid desc limit 0,100;

语句B:

select * from t_base_user order by oid desc limit 10000,100;

分别看下执行计划:

语句A的执行计划是:

explain select * from t_base_user order by oid desc limit 0,100;

结果:

 

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1

语句B的执行计划是:

explain select * from t_base_user order by oid desc limit 10000,100;

结果:

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1

到这里,我们会发现扫描的行数是完全不一样的,在语句B中,其实MySQL实际扫描1000100行记录,然后只返回100条记录,将前面的1000000条记录活生生的抛弃掉,你说这成本大不大,代价高不高? 看到这里,我们应该已经知道上面问题的答案了。

如何优化

    现在我们来说说如何优化LIMIT,我们知道,在offset比较大的时候,效率会非常低,所以,对LIMIT优化,要么限制分页的数量,要么降低offset的大小。 例如:

select * from t_base_user limit 100000,100

比如上面这语句,因为我们主键是连续的。

方法一 : 我们就可以通过这样来优化:

select * from t_base_user where oid between 100000 and 1000100;

此时如果我们看执行计划的话,其实type已经从all(全表扫描)扫描优化到range(范围查找),也走了PRIMARY索引。

方法二: 我们可以倒序LIMIT 如果我们表中一共有120万数据,此时我们就可以倒序LIMIT,如下所述:

select * from t_base_user order by oid desc limit 100;

或者这样:

select * from t_base_user where oid<1000000 order by oid desc limit 100;

同样也达到来优化的效果。

数据结构

  本文所有数据,均基于以下数据结构:

create table t_base_user(

oid bigint(20) not null primary key auto_increment,
name varchar(30) null comment "name",
email varchar(30) null comment "email",
age int null comment "age",
telephone varchar(30) null comment "telephone",
status tinyint(4) null comment "0 无效 1 有效",
created_at datetime null default now() comment "创建时间",
updated_at datetime null default now() comment "修改时间"
)
// 新增记录: insert into t_base_user(name,email,age,telephone,status,created_at,updated_at) values ("andyqian","andytohome",20,"15608411",1,now(),now());

这里提供一个简单的方法复制数据

insert into t_base_user(name,email,age,telephone,status) select name,email,age,telephone,status from t_base_user;

使用该语句,可以快速的复制数据。执行多次后,就能够生成不少数据,(备注: 该数据仅用作LIMIT关键字演示,新建索引,计算区分度其值偏差会比较大,请勿将该结果作为建索引的参考值。)

小结

  上面对MySQL LIMIT关键字做了详细的讲解,你可别小瞧它哦,它在平时开发中有很大的用处哦,例如: 在平时开发查询数据时,加上LIMIT后,查询效果可会大大增加,能节省不少时间呢。在查询数据时养成加上LIMIT是一个不错的习惯。

最后: 祝大家晚安!

相关阅读:

                                                        640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1

                                                                    扫码关注,一起进步

                                                      个人博客: http://www.andyqian.com

转载于:https://my.oschina.net/u/1462914/blog/1568047

你可能感兴趣的文章
MAC OX 安装rtx客户端和svn客户端
查看>>
Oracle GoldenGate 11g单向DDL配置实战
查看>>
【编译打包】nginx_1.6.2-1~precise.debian.tar.gz
查看>>
别总是把Windows和Linux混为一谈
查看>>
Terminal Services将改名为RDS
查看>>
NIO使用小结
查看>>
《Essential Linux Device Drivers》第1章
查看>>
[CTO札记]:多做[乘法],少些[加法]
查看>>
Microsoft Hyper-V Server 2012开启虚拟化-PowerShell
查看>>
玩 High API 系列之:快速实现身份验证
查看>>
移动的MobileMarket个人终于可以上传软件了
查看>>
linux多线程学习笔记六--一次性初始化和线程私有数据【转】
查看>>
Java中使用Runtime和Process类运行外部程序
查看>>
数据库泵(expdp/impdp)导入导出流程
查看>>
STM8S 串口应用 UART2 STM8S105
查看>>
ant 构建时遇到 “非法字符: \65279”的解决办法
查看>>
AES算法介绍
查看>>
数据库实例: STOREBOOK > 用户 > 编辑 用户: PUBLIC
查看>>
莫比乌斯反演学习【莫比乌斯反演】
查看>>
c#socket编程基础
查看>>