分页查询limit语法
1、因为商品非常多,总是会分页显示,这样显示的话方便大家查看。
2、我在翻页的时候,查询的性能是均衡的。
limit语法
select id,nickname,name,age,sex from user limit 10;
select id,nickname,name,age,sex from user limit 2000,10;
对整张表的数据的查看,然后显示前3个。
对整张表的数据的查看,然后偏移1个,然后显示前3个。
都是先执行select,然后再根据limit的要求去做(显示前几行,或者先偏移一下,再显示前几行。
limit对于SQL的查询,仅仅只是限制了查询的数据量的显示条数吗?
我们看到,id是主键,我们还给name给了唯一键,主键会自动创建主键索引,unique会自动创建唯一键索引。age和sex没有创建索引。
当我在这张表去找name=zhangsan的时候,MySQL是把这张表全扫了一遍,还是说只扫了一行就找到了?
关系型数据库是二维表,就是看扫的数据量来看效率。
我们加入explain关键字(查看SQL语句的执行计划,罗列出执行SQL的过程和信息,但是不是非常准确,MySQL的优化不会统计,性能指标只是大致)
我们看到,rows是1,扫了1行,我试过了,扫哪条信息都是扫1行!!!
因为name字段加了索引,所以不管记录在哪一行,都是扫1行。花费的时间,效率是一样的。
我们知道,age和sex没有索引,所以我们来查看看age和sex
因为age没有索引,计算机不知道后面会不会出现要显示的age值,所以肯定要全部扫1遍。 数据量越大,效率越低
如果不使用索引的话,还有什么办法可以提高查询的效率?
如果加了limit,MySQL会有优化,它知道我们只需要1行,它从上往下扫表,扫到这个age记录,而且知道我们只需要1行,它就停止了,直接返回了,这就效率高了。
但是explain却显示5行,因为explain看不到MySQL对limit的优化。
我们加入大量数据,测试一下limit优化
用下面的代码,可以迅速给表添加数据
delimiter $//分割符,以$结束,代表1个SQL
Create Procedure add_t_user (IN n INT)
// 存储过程的函数名 输入参数 变量 变量的类型
BEGIN
DECLARE i INT;
SET i=0;
WHILE i<n DO
INSERT INTO t_user VALUES(NULL,CONCAT(i+1,'@linzeyu.com'),i+1);
//0@linzeyu.com , 1@linzeyu.com ,2@linzeyu.com
//password就是 i+1
SET i=i+1;//每循环1次,i=i+1
END WHILE;//while的结束
END$//存储的过程的结构 BEGIN到END
delimiter ;//还原;为SQL的结束
call add_t_user(2000000);//增加数据量
现在数量就很多了,我们来看看效率
email没有索引,MySQL是把整张表全扫了1遍。
我们加上limit看看
看耗时。0.44秒。0秒。效率提升了!
加上limit是0.20秒,不加是0.44秒
刚才的limit是0秒,是扫描到第一行就结束了。这个是扫描1000001行。
如果是这个email有索引,那么效率就已经优化了,效率都是一样的。
如果是这个password有重复的,除非加索引,否则只能整张表扫。
limit分页的正确应用
现在有很多页
假如1页只显示20行,当我们用户在选择相应页码,我们怎么去select出来相应的数据呢?
点击第几页。偏移掉前面的页,然后显示选择的页的前20行
但是,我们在这里看到有效率的问题,总不能我们选前面几页就快,选后面的页就慢。
前面的页要一个个过一遍,这样就慢了!
效率低在M的偏移
我们要把M的偏移花费的性能过滤掉!
我们这样做:
利用主键id自动创建索引的原理
我们通过索引把M过滤掉!
优化成功!!!
我们真真正正这么去写:
索引是常量时间,过滤前面的数据。