zoukankan      html  css  js  c++  java
  • MySQL大数据量分页查询方法及其优化

    一、大数据量分页查询方法:

    1、直接使用数据库提供的SQL语句

      语句样式: MySQL中,可用如下方法: SELECT * FROM 表名称 LIMIT M,N

      适应场景: 适用于数据量较少的情况(元组百/千级)

      原因/缺点: 全表扫描,速度会很慢,且有的数据库结果集返回不稳定(如某次返回1,2,3,另外的一次返回2,1,3),Limit限制的是从结果集的M位置处取出N条输出,其余抛弃。

    //是用limit函数
    
    //取前5条数据
    select * from table_name limit 0,5 
    //或者
    select * from table_name limit 5 
    
    //查询第11到第15条数据
    select * from table_name limit 10,5

      limit关键字的用法:LIMIT [offset,] rows

      offset指定要返回的第一行的偏移量,rows第二个指定返回行的最大数目。初始行的偏移量是0(不是1)

    2、建立主键或唯一索引, 利用索引(假设每页10条)

      语句样式:可用如下方法:SELECT * FROM 表名称 WHERE id_pk > (pageNum*10) LIMIT M

      适应场景:适用于数据量多的情况(元组数上万)

      原因:索引扫描,速度会很快。有朋友提出:因为数据查询出来并不是按照pk_id排序的,所以会有漏掉数据的情况,只能方法3

    3、基于索引再排序

      语句样式:可用如下方法: SELECT * FROM 表名称 WHERE id_pk > (pageNum*10) ORDER BY id_pk ASC LIMIT M

      适应场景: 适用于数据量多的情况(元组数上万),最好ORDER BY后的列对象是主键或唯一索引,使得ORDER BY操作能利用索引被消除但结果集是稳定的

      原因:索引扫描,速度会很快。

    4、基于索引使用prepare(第一个问号表示pageNum,第二个?表示每页元组数)

      语句样式:MySQL中,可用如下方法: PREPARE stmt_name FROM SELECT * FROM 表名称 WHERE id_pk > (?* ?) ORDER BY id_pk ASC LIMIT M

      适应场景:大数据量

      原因:索引扫描,速度会很快。prepare语句又比一般的查询语句快一点。

    5、利用MySQL支持ORDER操作可以利用索引快速定位部分元组,避免全表扫描

      比如: 读第1000到1019行元组(pk是主键/唯一键).

      SELECT * FROM your_table WHERE pk>=1000 ORDER BY pk ASC LIMIT 0,20

    6、利用"子查询/连接+索引"快速定位元组的位置,然后再读取元组。

      道理同方法5。如(id是主键/唯一键,$page、$pagesize是变量):

    利用子查询示例:

    SELECT * FROM your_table WHERE id <= 
    (SELECT id FROM your_table ORDER BY id desc LIMIT ($page-1)*$pagesize ORDER BY id desc LIMIT $pagesize

    利用连接示例:

    SELECT * FROM your_table AS t1 
    JOIN (SELECT id FROM your_table ORDER BY id desc LIMIT ($page-1)*$pagesize AS t2 
    WHERE t1.id <= t2.id ORDER BY t1.id desc LIMIT $pagesize;

    二、优化方式

      mysql大数据量使用limit分页,随着页码的增大,查询效率越低下。

    1、直接用limit start, count分页语句:

      select * from product limit start, count

      当起始页较小时,查询没有性能问题,我们分别看下从10, 100, 1000, 10000开始分页的执行时间(每页取20条), 如下:

    select * from product limit 10, 20   0.016秒
    select * from product limit 100, 20   0.016秒
    select * from product limit 1000, 20   0.047秒
    select * from product limit 10000, 20   0.094秒
    //我们已经看出随着起始记录的增加,时间也随着增大, 这说明分页语句limit跟起始页码是有很大关系的,那么我们把起始记录改为40w看下(也就是记录的一般左右)                                    
    
    select * from product limit 400000, 20   3.229秒
    //再看我们取最后一页记录的时间
    select * from product limit 866613, 20   37.44秒
    
    //像这种分页最大的页码页显然这种时间是无法忍受的。

      从中我们也能总结出两件事情:

      (1)limit语句的查询时间与起始记录的位置成正比

      (2)mysql的limit语句是很方便,但是对记录很多的表并不适合直接使用。

    2、对limit分页问题的性能优化方法

      利用表的覆盖索引来加速分页查询:我们都知道,利用了索引查询的语句中如果只包含了那个索引列(覆盖索引),那么这种情况会查询很快。

      因为利用索引查找有优化算法,且数据就在查询索引上面,不用再去找相关的数据地址了,这样节省了很多时间。另外Mysql中也有相关的索引缓存,在并发高的时候利用缓存就效果更好了。

      在我们的例子中,我们知道id字段是主键,自然就包含了默认的主键索引。现在让我们看看利用覆盖索引的查询效果如何:

    //这次我们之间查询最后一页的数据(利用覆盖索引,只包含id列),如下:
    select id from product limit 866613, 20 0.2秒
    //相对于查询了所有列的37.44秒,提升了大概100多倍的速度
    
    //那么如果我们也要查询所有列,有两种方法,
    //一种是id>=的形式,
    //另一种就是利用join,看下实际情况:
    
    SELECT * FROM product WHERE ID > =(select id from product limit 866613, 1) limit 20
    //查询时间为0.2秒!
    
    //另一种写法
    SELECT * FROM product a JOIN (select id from product limit 866613, 20) b ON a.ID = b.id
    //查询时间也很短!
  • 相关阅读:
    UVA 10618 Tango Tango Insurrection
    UVA 10118 Free Candies
    HDU 1024 Max Sum Plus Plus
    POJ 1984 Navigation Nightmare
    CODEVS 3546 矩阵链乘法
    UVA 1625 Color Length
    UVA 1347 Tour
    UVA 437 The Tower of Babylon
    UVA 1622 Robot
    UVA127-"Accordian" Patience(模拟)
  • 原文地址:https://www.cnblogs.com/goloving/p/8565017.html
Copyright © 2011-2022 走看看