1. 背景

假设有如下SQL语句:

SELECT * FROM table1 LIMIT offset, rows

这是一条典型的LIMIT语句,常见的使用场景是,某些查询返回的内容特别多,而客户端处理能力有限,希望每次只取一部分结果进行处理。

上述SQL语句的实现机制是:

  1. 从“table”表中读取offset+rows行记录
  2. 抛弃前面的offset行记录,返回后面的rows行记录作为最终结果。

这种实现机制存在一个弊端:虽然只需要返回rows行记录,但却必须先访问offset行不会用到的记录。对一张数据量很大的表进行查询时,offset值可能非常大,此时limit语句的效率就非常低了。

2. 简单查询的LIMIT优化

假设表message表中有10万行记录,每次取1000条。
优化前:

SELECT message.* FROM message LIMIT 0,1000
SELECT message.* FROM message LIMIT 1000,1000
SELECT message.* FROM message LIMIT 2000,1000
……
SELECT message.* FROM message LIMIT 998000,1000
SELECT message.* FROM message LIMIT 999000,1000

优化后(利用自增主键,避免offset的使用):

SELECT message.* FROM message WHERE uid>0 LIMIT 1000
SELECT message.* FROM message WHERE uid>1000 LIMIT 1000
SELECT message.* FROM message WHERE uid>2000 LIMIT 1000
……
SELECT message.* FROM message WHERE uid>998000 LIMIT 1000
SELECT message.* FROM message WHERE uid>999000 LIMIT 1000

在笔者的机器上,优化前,SQL语句从前往后越来越慢(最后一条语句执行了150毫秒),而优化后,每条语句的耗时都是微妙级的。

3. 复杂查询的LIMIT优化

实际工程中遇到的查询,通常要复杂些,比如,多表查询、条件查询。这种情况下,查询结果通常不是按照自增主键的顺序逐一排列的。

例如,对于下述SQL语句,就不能像第二节那样优化了:

SELECT timerec FROM message WHERE evttype = 1 AND nodename = 'node1'
LIMIT 0,1000
……
SELECT timerec FROM message WHERE evttype = 1 AND nodename = 'node1'
LIMIT 999000,1000
……

优化方案:建立临时表(含自增主键)存储数十万行的查询结果,之后用第二节的方法分多次访问临时表、获取数据。

  1. 创建临时表
CREATE TEMPORARY TABLE tmp_timerec(
 `uid` bigint(20) NOT NULL AUTO_INCREMENT,
 `timerec` datetime NOT NULL,
 PRIMARY KEY (`uid`)) 
  1. 插入查询结果到临时表
INSERT INTO tmp_timerec
SELECT null,timerec FROM message
WHERE evttype = 1 AND nodename = ‘node1’
  1. 分多次查询临时表
SELECT timerec FROM tmp_timerec where uid > 0 LIMIT 1000
……
SELECT timerec FROM tmp_timerec where uid > 999000 LIMIT 1000

最后,附上MySQL性能优化系列的全部链接:

[MySQL性能优化系列]LIMIT语句优化的更多相关文章

  1. 浅谈mysql配置优化和sql语句优化【转】

    做优化,我在这里引用淘宝系统分析师蒋江伟的一句话:只有勇于承担,才能让人有勇气,有承担自己的错误的勇气.有承担错误的勇气,就有去做事得勇气.无论做什么事,只要是对的,就要去做,勇敢去做.出了错误,承担 ...

  2. 数据库的优化(表优化和sql语句优化)

    在这里主要是分为表设计优化和sql语句优化两方面来实现. 首先的是表设计优化: 1.数据行的长度不要超过8020字节.如果是超过这个长度的话这条数据会占用两行,减低查询的效率. 2.能用数字类型就不要 ...

  3. mysql优化和sql语句优化总结

    mysql性能优化 1. EXPLAIN 你的 SELECT 查询.使用 EXPLAIN 关键字可以让你知道MySQL是如何处理你的SQL语句的.这可以帮你分析你的查询语句或是表结构的性能瓶颈. 2. ...

  4. mysql优化之SQL语句优化

    Mysql优化是一个老生常谈的问题, 优化的方向也优化很多:从架构层;从设计层;从存储层;从SQL语句层; 今天讲解一下从SQL语句层: 这个部分是程序员最容易把控的地方,也是最容易忽视的地方. 一个 ...

  5. MySql(八):MySQL性能调优——Query 的优化

    一.理解MySQL的Query Optimizer MySQL Optimizer是一个专门负责优化SELECT 语句的优化器模块,它主要的功能就是通过计算分析系统中收集的各种统计信息,为客户端请求的 ...

  6. 数据库性能调优——sql语句优化(转载及整理) —— 篇1

    一.问题的提出                    在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的的编写等体会不出SQL语句各种写法的性能优劣,但是如果将应用系统提交实 ...

  7. 数据库性能优化之SQL语句优化

    一.问题的提出 在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的编写等是体会不出SQL语句各种写法的性能优劣,但是如果将应用系统提交实际应用后,随着数据库中数据的增加,系统 ...

  8. ORACLE性能优化之SQL语句优化

    版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[+]   操作环境:AIX +11g+PLSQL 包含以下内容: 1.  SQL语句执行过程 2.  优化器及执行计划 3.  合 ...

  9. 数据库性能优化之SQL语句优化(上)

    一.问题的提出 在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的编写等体会不出SQL语句各种写法的性能优劣,但是如果将应用系统提交实际应用后,随着数据库中数据的增加,系统的 ...

随机推荐

  1. ZOJ Problem Set - 1337 Pi 最大公约数

    这道题目的关键在于怎么求两个整数的最大公约数,这里正好复习一下以前的知识,如下: 1.设整数a和b 2.如果a和b都为0,则二者的最大公约数不存在 3.如果a或b等于0,则二者的最大公约数为非0的一个 ...

  2. JavaScript(Node.js)+ Selenium自动化测试

    Selenium is a browser automation library. Most often used for testing web-applications, Selenium may ...

  3. Hibernate之HQL查询的一些例子

    Hibernate配备了一种非常强大的查询语言,就是HQL(hibernate query language),HQL看上去很像sql,但只是语法结构上相似,HQL是一种面向对象的查询,他可以理解继承 ...

  4. Win8.1安装mysql-installer-community-5.6.21.0.mis

    引言 我本机是win8.1,在官网下载的这个安装是32位和64位都能装,安装步骤参考:http://jingyan.baidu.com/article/67662997305dcd54d51b84d4 ...

  5. Hibernate —— Entity.hbm.xml

    一.简述 1.对象关系映射文件,用于映射实体类和关系数据库数据表之间的一个 xml 文件. 2.通过 Entity.hbm.xml 映射文件,Hibernate 可以理解持久化类和数据表之间的对应关系 ...

  6. 解决Android工程里的xml文件自动提示问题

    昨天晚上看某培训机构的Android的 视频教程,看到他在写布局的XML文件时,有很方便的自动提示功能.我就在自己的Eclipse里试了一下,可是我的没实现.就到网上查,很多都说:在 Window-& ...

  7. 【开源】SoDiaoEditor 可能是目前最好用的开源电子病历编辑器(B/S架构)

    此刻我的内心是忐忑的,这个标题给了我很大的压力,虽然很久以前我就在github上搜索一圈了,也没发现有其他更好的开源电子病历编辑器,如各位亲发现有更好的,烦请知会我一声. 该编辑器其实已经憋了很久了, ...

  8. Unity3D 5.x 交互功能 - 碰撞检测函数

    1,给第一人称控制器添加脚本:playercollisions.js 脚本中只定义变量,先不添加方法: #pragma strict var door_open_time:float=3.0; var ...

  9. 总结shell

    总结shell里面一些初学者不容易懂得点,因为我本身就是初学者,所以有一些知识点是不容易通过字面意思理解的,下面写在这里. (便于理解的一个方法就是举例子)举个例子就是哪些容易学,哪些不容易理解:丁是 ...

  10. MongoDB基础入门003--使用官方驱动操作mongo,C#

    本篇先简单介绍一下,使用官方驱动来操作MongoDB.至于MongoDB原生的增删改查语句,且等以后再慢慢学习. 一.操作MongoDB的驱动主要有两个 1.官方驱动:https://github.c ...