日常我们分页时会用到MySQL的limit字段去处理,那么使用limit时,有什么需要优化的地方吗?
我们来做一个试验来看看limit的效率问题:
环境:CentOS 6 & MySQL 5.7
1、建议一个实验表:

collect(id[主键], title[varchar], info[text], vtype[tinyint]);
Engine: MyISAM

2、关闭查询缓存:
MySQL中的 query_cache_size 和 query_cache_type 参数。

mysql> show variables like 'query_cache%';
+------------------------------+---------+
| Variable_name | Value |
+------------------------------+---------+
| query_cache_limit | 1048576 |
| query_cache_min_res_unit | 4096 |
| query_cache_size | 1048576 |
| query_cache_type | OFF |
| query_cache_wlock_invalidate | OFF |
+------------------------------+---------+
5 rows in set (0.06 sec)

查询缓存命中情况:Qcache_hits

mysql> show status like '%qcache%';
+-------------------------+---------+
| Variable_name | Value |
+-------------------------+---------+
| Qcache_free_blocks | 1 |
| Qcache_free_memory | 1031832 |
| Qcache_hits | 0 |
| Qcache_inserts | 0 |
| Qcache_lowmem_prunes | 0 |
| Qcache_not_cached | 81 |
| Qcache_queries_in_cache | 0 |
| Qcache_total_blocks | 1 |
+-------------------------+---------+
8 rows in set (0.00 sec)

关闭查询缓存:

set global query_cache_size=0
set global query_cache_type=0

Note:

select SQL_NO_CACHE * from table_name;
使用SQL_NO_CACHE参数并不代表不使用缓存,而是此次查询不会缓存,MySQL中如有缓存还是会返回缓存数据,
也就是说,可能同一条sql,第一次查询时间很长,第二次就很短。
我在实验中,先是使用的xampp中的MariaDB,发现无论我怎么设置(包括关闭缓存,清除缓存),都能使用到缓存,也就是我第二次查询时间很短。
所以之后我使用了CentOS 6内网机中的MySQL 5.7做实验。

3、开始试验:

3.a、无索引情况
collect表插入10万条数据。【此时表无索引】

mysql> select count(*) from collect;
+----------+
| count(*) |
+----------+
| 100001 |
+----------+
1 row in set (0.00 sec)

select id,title字段,limit 1000,1 非常快

mysql> FLUSH QUERY CACHE;
Query OK, 0 rows affected, 1 warning (0.03 sec) mysql> select SQL_NO_CACHE id,title from collect limit 1000,10;
10 rows in set, 1 warning (0.07 sec)

select id,title字段,limit 90000,1 慢了

mysql> FLUSH QUERY CACHE;
Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> select SQL_NO_CACHE id,title from collect limit 90000,10;
10 rows in set, 1 warning (2.02 sec)

select id字段,limit 90000,1 非常快

mysql> FLUSH QUERY CACHE;
Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> select SQL_NO_CACHE id from collect limit 90000,10;
10 rows in set, 1 warning (0.02 sec)

那么我们想查询title怎么快呢?
网上有的解决方式为:用id做条件去查 【可用,效率可以】

mysql> FLUSH QUERY CACHE;
Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> select SQL_NO_CACHE id,title from collect where id>=(select id from collect order by id limit 90000,1) limit 10;
10 rows in set (0.01 sec) mysql> select SQL_NO_CACHE id,title from collect order by id limit 90000,10;
10 rows in set (2.07 sec)

以上可以看出来,用id做limit,然后再以id为条件查询,效率比直接id,title做limit快的多。

3.b 加单个索引
那么我们以其他字段做where条件呢?如vtype字段。
为vtype建立索引:【该方法很慢】

ALTER TABLE collect ADD INDEX search(vtype);

用vtype做where条件做limit 90000,10

mysql> FLUSH QUERY CACHE;
Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> select SQL_NO_CACHE id from collect where vtype=1 order by id limit 90000,10;
Empty set (2.50 sec)

vtype有索引为何这么慢呢?个人猜测可能是做了全表扫描而没走索引
试验一下 limit 1000,10呢?

mysql> FLUSH QUERY CACHE;
Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> select SQL_NO_CACHE id from collect where vtype=1 order by id limit 1000,10;
10 rows in set (0.03 sec)

计算一下 0.03*90 = 2.7 和 limit 90000,10 差不多

那么加复合索引呢?会不会提高效率呢?

3.c、(vtype,id)复合索引 【只查主键非常快】

mysql> alter table collect add index search(vtype,id);
Query OK, 100001 rows affected (8.72 sec)
Records: 100001 Duplicates: 0 Warnings: 0 mysql> FLUSH QUERY CACHE;
Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> select SQL_NO_CACHE id from collect where vtype=1 order by id limit 90000,10;
Empty set (0.01 sec) mysql> FLUSH QUERY CACHE;
Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> select SQL_NO_CACHE id,title from collect where vtype=1 order by id limit 90000,10;
Empty set (2.56 sec)

可以看出来,(vtype,id)复合索引下,limit偏移量大的情况下,只查询主键id,是非常快的。

3.d、(id,vtype)复合索引 【没有vtype,id快】

mysql> drop index search on collect;
Query OK, 100001 rows affected (4.31 sec)
Records: 100001 Duplicates: 0 Warnings: 0 mysql> select SQL_NO_CACHE id from collect where vtype=1 order by id limit 90000,10;
Empty set (2.28 sec) mysql> alter table collect add index search(id,vtype);
Query OK, 100001 rows affected (6.46 sec)
Records: 100001 Duplicates: 0 Warnings: 0 mysql> select SQL_NO_CACHE id from collect where vtype=1 order by id limit 90000,10;
Empty set (0.07 sec) mysql> select SQL_NO_CACHE id,title from collect where vtype=1 order by id limit 90000,10;
Empty set (1.99 sec)

(id,vtype)复合索引下,只查询主键id的limit看起来好像和(vtype,id)复合索引没什么区别,但是我试验中,将数据加到160万,就能看出来,(vtype,id)复合索引几乎不受影响,(id,vtype)复合索引却开始变慢了。

那么现在查询到id了,我们通过id去找title字段值。使用in去找,你会发现还是很快的。

select SQL_NO_CACHE * from collect where id in(901744,901772,901773,901794);
4 rows in set (0.10 sec)

4、最后

再测试100万,160万,结论为(vtype,id)复合索引查id,MySQL in()去查多个id的值,完全可以,查询效率没问题,还是很快,不过再往上,我就没再测试过了。

5、总结

以collect(id[主键], title[varchar], info[text], vtype[tinyint]); Engine: MyISAM表,为例:

数据160万,查询条件vtype,查title字段

优化Limit步骤:

1、加(vtype,id)复合索引

2、select id from collect where vtype=1 limit 900000,10;

3、select id,title from collect where id in(1,2,3,4,5,6,7,8,9,10);

MySQL的limit分页性能测试加优化的更多相关文章

  1. mysql的limit经典用法及优化

    用法一   SELECT `keyword_rank`.* FROM `keyword_rank` WHERE (advertiserid='59') LIMIT 2 OFFSET 1;   比如这个 ...

  2. mysql数据库limit分页,排序操作

    看到网上很多朋友在问,limit分页之后按照字段属性排序的问题,在这里分享一下我的用法: 1.网上答案: 每页显示5个,显示第三页信息,按照年龄从小到大排序 select * from student ...

  3. 记一次mysql关于limit和orderby的优化

    针对于大数据量查询,我们一般使用分页查询,查询出对应页的数据即可,这会大大加快查询的效率: 在排序和分页同时进行时,我们一定要注意效率问题,例如: select a.* from table1 a i ...

  4. 在MySQL中如何使用覆盖索引优化limit分页查询

    背景 今年3月份时候,线上发生一次大事故.公司主要后端服务器发生宕机,所有接口超时.宕机半小时后,又自动恢复正常.但是过了2小时,又再次发生宕机. 通过接口日志,发现MySQL数据库无法响应服务器.在 ...

  5. MYSQL分页limit速度太慢优化方法

    http://www.fienda.com/archives/110 在mysql中limit可以实现快速分页,但是如果数据到了几百万时我们的limit必须优化才能有效的合理的实现分页了,否则可能卡死 ...

  6. mysql limit分页优化方法分享

    同样是取10条数据  select * from yanxue8_visit limit 10000,10 和  select * from yanxue8_visit limit 0,10  就不是 ...

  7. [MySQL] LIMIT 分页优化

    背景:LIMIT 0,20 这种分页方式,随着 offset 值的不断增大,当达到百万级时,一条查询就需要1秒以上,这时可以借助索引条件的查询来优化. SQL:select * from member ...

  8. MySQL 百万级分页优化

    MySQL 百万级分页优化 http://www.jb51.net/article/31868.htm 一般刚开始学SQL的时候,会这样写 : , ; 但在数据达到百万级的时候,这样写会慢死 : , ...

  9. MySQL 百万级分页优化(Mysql千万级快速分页)(转)

    http://www.jb51.net/article/31868.htm 以下分享一点我的经验 一般刚开始学SQL的时候,会这样写 复制代码 代码如下: SELECT * FROM table OR ...

随机推荐

  1. Altium Designer(AD)使用笔记

    在PCB中间打洞,螺丝孔等 制作PCB螺丝孔 1 在Keepout层首先绘制一个圆形(矩形): 2 在绘制PCB时,选中该图形,Tool>>Convert>>create bo ...

  2. Google File System 论文阅读笔记

    核心目标:Google File System是一个面向密集应用的,可伸缩的大规模分布式文件系统.GFS运行在廉价的设备上,提供给了灾难冗余的能力,为大量客户机提供了高性能的服务. 1.一系列前提 G ...

  3. [Linux] 013 其他文件搜索命令

    1. 文件搜索命令:locate 命令名称:locate 命令所在路径:/bin/locate 执行权限:所有用户 语法:locate 文件名 功能描述:在文件资料库中查找文件 范例: $ locat ...

  4. secureCRT安装,破解,连接linux机器(含安装包)

    1. 为什么需要安装secureCRT 我们的项目运行在服务器上,如果出现什么问题,或者升级的时候,需要对服务器进行操作,把处理好的项目发布到服务器上.如果我们就在服务器身边,那么直接在服务器上进行操 ...

  5. Codeforces 1105C (DP)

    题面 传送门 分析 这种计数问题,要不是纯数学推公式,要不就是dp 先处理出[l,r]中除3余0,1,2的数的个数,记为cnt0,cnt1,cnt2 设\(dp[i][j]\)表示前i个数的和除3余j ...

  6. 关于自带的sql developer修改java.exe版本的解决办法

    第一次安装oracle11gR2后,就很好奇的点了一下,当点击应用程序开发下的sql developer后,就弹出一个窗口,要选择一个java.exe的路径,我就讲本机中的JDK1.7下的java.e ...

  7. sql server 自优化

    大数据量下的SQL Server数据库自身优化 发布时间:2013-12-17 15:19:00 来源:论坛 作者:佚名   关键字:数据库开发 1.1:增加次数据文件 从SQL SERVER 200 ...

  8. 洛谷 P2863 [USACO06JAN]牛的舞会The Cow Prom(Tarjan)

    一道tarjan的模板水题 在这里还是着重解释一下tarjan的代码 #include<iostream> #include<cstdio> #include<algor ...

  9. java 局部变量与成员成员变量的区别

    package java04; /* 局部变量和成员变量的不同: 1.定义的位置不一样 局部变量:定义在方法内部 成员变量:在方法外部,直接写在类中 2.作用范围不一样 局部变量:只有方法中能使用,除 ...

  10. poj 3468: A Simple Problem with Integers (树状数组区间更新)

    题目链接: http://poj.org/problem?id=3468 题目是对一个数组,支持两种操作 操作C:对下标从a到b的每个元素,值增加c: 操作Q:对求下标从a到b的元素值之和. 这道题也 ...