用会 MySQL LIMIT

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

前言

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

LIMIT是什么?

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

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

这里着重须要注意的是: offset为开始角标,count表明数量,以下图所示:数据结构

                  (图片来源: mysqltutorial)优化

理解了这个概念以后,咱们就可以知道下面这两个语句的意思了:spa

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;

结果:

 

语句B的执行计划是:

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

结果:

到这里,咱们会发现扫描的行数是彻底不同的,在语句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是一个不错的习惯。

最后: 祝你们晚安!

相关阅读:

写会MySQL索引

读懂MySQL执行计划

                                                        

                                                                    扫码关注,一块儿进步

                                                      我的博客: http://www.andyqian.com

相关文章
相关标签/搜索