很久以前的一次面试中,被面试官问到这个问题,由于平时用到的分页方法不多,只从索引、分表、使用子查询精准定位偏移以外,没有使用到其它方法。

后来在看其它博客看到了一些不同的方案,也一直没有整理。今天有时间,整理出来,分享给大家。

一,最常见MYSQL最基本的分页方式:

select * from content order by id desc limit 0, 10

在中小数据量的情况下,这样的SQL足够用了,唯一需要注意的问题就是确保使用了索引。随着数据量的增加,页数会越来越多,查看后几页的SQL就可能类似:

select * from content order by id desc limit 10000, 10

一言以蔽之,就是越往后分页,LIMIT语句的偏移量就会越大,速度也会明显变慢。
此时,我们可以通过2种方式:

一,子查询的分页方式来提高分页效率,飘易用的SQL语句如下:

SELECT * FROM `content` WHERE id> (SELECT id FROM `content` ORDER BY id desc LIMIT ".($page-1)*$pagesize.", 1) ORDER BY id desc LIMIT $pagesize

为什么会这样呢?因为子查询是在索引上完成的,而普通的查询时在数据文件上完成的,通常来说,索引文件要比数据文件小得多,所以操作起来也会更有效率。(via)通过explain SQL语句发现:子查询使用了索引!

id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY content range PRIMARY PRIMARY 4 NULL 6264 Using where
2 SUBQUERY content index NULL PRIMARY 4 NULL 27085 Using index

经过飘易的实测,使用子查询的分页方式的效率比纯LIMIT提高了14-20倍!

二,JOIN分页方式

select * FROM `content` AS t1
JOIN (SELECT id FROM `content` ORDER BY id desc LIMIT ".($page-1)*$pagesize.", 1) AS t2
WHERE t1.id

经过我的测试,join分页和子查询分页的效率基本在一个等级上,消耗的时间也基本一致。explain SQL语句:

id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY system NULL NULL NULL NULL 1
1 PRIMARY t1 range PRIMARY PRIMARY 4 NULL 6264 Using where
2 DERIVED content index NULL PRIMARY 4 NULL 27085 Using index

三,使用MYSQL的FOUND_ROWS()函数
Mysql FOUND_ROWS() 函数结合SQL_CALC_FOUND_ROWS在SELECT中可以得到两个结果:
1. 得到Limit的内容
2. 得到去除Limit以后所有行数

SELECT语句中经常可能用LIMIT限制返回行数。有时候可能想要知道如果没有LIMIT会返回多少行,但又不想再执行一次相同语句。那么,在SELECT查询中包含SQL_CALC_FOUND_ROWS选项,然后执行FOUND_ROWS()就可以了:

select SQL_CALC_FOUND_ROWS * FROM tbl_name WHERE id > 100 LIMIT 10;
SELECT FOUND_ROWS();

其中SQL_CALC_FOUND_ROWS 告诉Mysql将sql所处理的行数记录下来,FOUND_ROWS() 则取到了这个纪录。 虽然也是两个语句,但是只执行了一次主查询,所以效率比原来要高很多。

1. 如果在前一条语句中使用SQL_CALC_FOUND_ROWS选项,FOUND_ROWS()将返回第一条语句没有LIMIT时返回的行数。
2. 如果在前一条语句中没有使用SQL_CALC_FOUND_ROWS选项,FOUND_ROWS()将返回前一条语句实际返回的行数。
如果使用 SELECT SQL_CALC_FOUND_ROWS,MySQL必须计算所有结果集的行数。尽管这样,总比再执行一次不使用LIMIT的查询要快多了吧,因为那样结果集要返回客户端滴。(另外:应该不单是没有将结果集返回的原因,还有原因可能是比如LIKE之类比较费劲的SQL不需要再去劳累一次。)

-- 注意下面语句中的条件 LIKE
SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name WHERE Name LIKE '%string%' id > 100 LIMIT 10;
SELECT FOUND_ROWS();

-- 上面语句等价于下面语句,但性能方面应该提升非常非常的明显:
SELECT COUNT(*) FROM tbl_name WHERE Name LIKE '%string%' ;
SELECT * FROM tbl_name WHERE Name LIKE '%string%' id > 100 LIMIT 10;

参考博客:

http://blog.hexu.org/archives/1328.shtml

http://hi.baidu.com/thinkinginlamp/blog/item/17476d22d66876a14623e81d.html

http://www.piaoyi.org/php/MySQL-SUBQUERY-index.html

MySQL高效分页解决方案集(转)的更多相关文章

  1. MySQL高效分页解决方案集

    一,最常见MYSQL最基本的分页方式: select * from content order by id desc limit 0, 10 在中小数据量的情况下,这样的SQL足够用了,唯一需要注意的 ...

  2. MySQL高效分页-mybatis插件PageHelper改进

    MySQL分页在表比较大的时候,分页就会出现性能问题,MySQL的分页逻辑如下:比如select * from user limit 100000,10 它是先执行select * from user ...

  3. mysql高效分页方案及原理

    很久以前的一次面试中,被面试官问到这个问题,由于平时用到的分页方法不多,只从索引.分表.使用子查询精准定位偏移以外,没有使用到其它方法. 后来在看其它博客看到了一些不同的方案,也一直没有整理.今天有时 ...

  4. mysql 高效分页控件及c#调用实例

    第一.首先在mysql中创建一个存储过程 BEGIN /* @selectSql VARCHAR(5000), --sql语句 @orderWhere VARCHAR(200), --排序条件 @pa ...

  5. MySQL 高效分页

    create PROCEDURE USP_GetByPager( _pageindex int, _pagesize int ) BEGIN )*_pagesize; select * from A ...

  6. MySql高效分页SQL

    public string GetQuerySql(ITSPAreaQueryModel model, object state = null) { ); sqlBuilder.AppendForma ...

  7. 1 构建Mysql+heartbeat+DRBD+LVS集群应用系统系列之DRBD的搭建

    preface 近来公司利润上升,购买了10几台服务器,趁此机会,把mysql的主从同步的架构进一步扩展,为了适应日益增长的流量.针对mysql架构的扩展,先是咨询前辈,后和同事探讨,准备采用Mysq ...

  8. T-SQL 使用WITH高效分页

    一.WITH AS 含义     WITH AS短语,也叫做子查询部分(subquery factoring),可以让你做很多事情,定义一个SQL片断,该SQL片断会被整个SQL语句所用到.有的时候, ...

  9. oracle sqlserver mysql数据库分页

    1.Mysql的limit用法 在我们使用查询语句的时候,经常要返回前几条或者中间某几行数据,这个时候怎么办呢?不用担心,mysql已经为我们提供了这样一个功能. SELECT * FROM tabl ...

随机推荐

  1. Atitit dsl对于数组的处理以及main函数的参数赋值

    Atitit dsl对于数组的处理以及main函数的参数赋值 1.1. 词法解析..添加了[] 方括号的解析支持1 1.2. Ast建立.添加了数组参数的支持..使用了递归下降法..getparam ...

  2. Atitit 基于dom的游戏引擎

    Atitit 基于dom的游戏引擎 1. 添加sprite控件(cocos,createjs,dom)1 1.1.1. Cocos1 1.1.2. createjs1 1.1.3. Dom模式2 1. ...

  3. 使用python原生的方法实现发送email

    使用python原生的方法实现发送email import smtplib from email.mime.text import MIMEText from email.mime.multipart ...

  4. 使用__slots__限定实例的成员列表

    使用__slots__限定实例的成员列表 默认情况下,python对象队象的每个实例(instance)都会有一个字典来存储该实例的属性,这样做的好处在于运行时期每个对象可以任意设置新的属性.而相对应 ...

  5. Java Synchronized Blocks

    From http://tutorials.jenkov.com/java-concurrency/synchronized.html By Jakob Jenkov   A Java synchro ...

  6. 原生JS实现分页效果1.0

    不太完整,写的太急,等等加上完整注释,写起来还是有些难度的,写的有点水,后面再改进改进. <!DOCTYPE html><html lang="en">&l ...

  7. .NET面试题解析(04)-类型、方法与继承

      系列文章目录地址: .NET面试题解析(00)-开篇来谈谈面试 & 系列文章索引 做技术是清苦的.一个人,一台机器,相对无言,代码纷飞,bug无情.须梦里挑灯,冥思苦想,肝血暗耗,板凳坐穿 ...

  8. MongoDB的学习--索引类型和属性

    索引类型 MongDB的索引分为以下几种类型:单键索引.复合索引.多键索引.地理空间索引.全文本索引和哈希索引 单键索引(Single Field Indexes) 在一个键上创建的索引就是单键索引, ...

  9. js中页面刷新和页面跳转的方法总结

    .js中cookie的基本用法简介 2009-12-15 js中页面刷新和页面跳转的方法总结 文章分类:Web前端 关键字: javascript js中页面刷新和页面跳转的方法总结 1.histor ...

  10. 大数据下的Distinct Count(一):序

    在数据库中,常常会有Distinct Count的操作,比如,查看每一选修课程的人数: select course, count(distinct sid) from stu_table group ...