zoukankan      html  css  js  c++  java
  • mysql分页查询详解

      我们做的后端项目一般都会有admin管理端,当管理端将要展示数据的时候,就需要用到分页。所以分页的考查在面试中也相当多。在mysql中进行分页查询时,一般会使用limit查询,而且通常查询中都会使用order by来排序。但是在表数据量比较大的时候,例如查询语句片段limit 10000,20,数据库会读取10020条数据,然后把前10000条丢弃,把最后的20条返回给你,这种消耗是可以避免的,也是没必要的。下边介绍几种优化方法:

    1. 让分页操作在索引中进行

        一般表中经常作为条件查询的列都会建立索引,例如如下查询

    SELECT 
        msg_id, 
        msg_content 
    FROM message 
    ORDER BY 
        gmt_create desc 
    LIMIT 100, 20;  

    可以写成如下方式

    SELECT 
        msg_id, 
        msg_content 
    FROM message   
    INNER JOIN (  
        SELECT 
            msg_id 
        FROM message  
        ORDER BY gmt_create 
        LIMIT 100, 20  
    ) AS page USING(msg_id);      

     这样当前查询页的内容就只会在索引中进行,当得到当前页的msg_id再统一通过一个INNER JOIN得到最终要得到的数据详情,避免了对大量数据详情进行操作的消耗。当然JOIN操作也可以通过子查询实现,不过书中介绍5.6之前版本的mysql相比子查询还是优先使用JOIN。

    2. 显式指定要查询的索引列范围

      如方法一中的gmt_create是建立索引的列,而且你也知道要查询的时间范围,这样你就可以通过如下查询语句:这样数据库通过一个范围查询就可以得到想要的数据。

    SELECT 
        msg_id, 
        msg_content 
    FROM message  
    WHERE gmt_create BETWEEN #startTime# AND #endTime#  
    ORDER BY gmt_create desc

    3. OFFSET作为查询条件显式指定

    我们可以在查询参数中显式指定一个查询时间,叫做lastVisitTime吧。我们查询第一页可以用如下语句:

    SELECT 
        msg_id, 
        msg_content 
    FROM message  
    ORDER BY gmt_create desc  
    LIMIT 20

     我们把读出来的数据的最后一条数据的gmt_create字段记录在lastVisitTime字段中,那么后边页的查询就可以用如下语句实现:这种查询方式,无论你查询多少页,分页都不会是影响效率的因素。

    SELECT 
        msg_id, 
        msg_content 
    FROM message  
    WHERE gmt_create < #lastVisitTime#  
    ORDER BY gmt_create desc  
    LIMIT 20; 

     4. limit在MySQL中的用法

      limit是mysql的语法,select * from table limit m,n。其中m是指记录开始的index,从0开始,表示第一条记录,n是指从第m+1条开始,取n条。select * from tablename limit 2,4。即取出第3条至第6条,4条记录。

      注意m表示的是从第几条数据开始读取,并不是记录的主键id号。(you know it)

    5. limit与offset用法比较

    SELECT  
        keyword  
    FROM  
        keyword_rank  
    WHERE  
        advertiserid='59'  
    order by  
        keyword  
    LIMIT 2 OFFSET 1; 
            该用法,limit后面跟的是2条数据,offset后面是从第1条开始读取
    
    ****************************************************************************************************
    SELECT  
        keyword  
    FROM  
        keyword_rank  
    WHERE  
        advertiserid='59'  
    ORDER BY  
        keyword  
    LIMIT 2 ,1;  
            该用法,limit后面是从第2条开始读,读取1条信息。
    
    注意:Mysql中计数也是从0开始读数的。

    6. 优化Limit的用法

      当一个查询语句偏移量offset很大的时候,如select * from table limit 10000,10 , 最好不要直接使用limit,而是先获取到offset的id后,再直接使用limit size来获取数据。效果会好很多。

    SELECT
        *
    FROM
        customers
    WHERE
        customer_id >= (
            SELECT
                customer_id
            FROM
                customers
            ORDER BY
                customer_id
            LIMIT 10000,
            1
        )
    LIMIT 10;

    相关联的一些查询用法实例总结如下:

    select * from table limit 5; --返回前5行
    
    select * from table limit 0,5; --同上,返回前5行
    
    select * from table limit 5,10; --返回6-15行
    
    附:(sql server支持,而mysql不支持的一些用法)
    1. select top 2 * from table; 选取表中前2条记录
    2. select top 50 persent from table; 选取表中50%的记录

    7. oracle是如何分页的?

    在oracle中采用ROWNUM实现分页查询:
    1. 选取前5条记录
    SELECT
        *
    FROM
        Persons
    WHERE
        ROWNUM <= 5;
    
    2. 从表Sys_option(主键为sys_id)中从第10条记录开始检索20条记录,语句如下
    SELECT
        *
    FROM
        (
            SELECT
                ROWNUM R,
                t1.*
            FROM
                Sys_option
            WHERE
                rownum < 30
        ) t2
    WHERE
        t2.R >= 10

     

  • 相关阅读:
    一致性哈希的理解与实践
    nil in Go
    为什么Go没有math.Min/Max(int, int) 函数?
    What happens when I type kubectl run?
    kubelet简要分析
    编译安装nginx和模块
    nginx与tengine添加check模块(nginx_upstream_check_module)
    多台ESXI 6.5 添加 iSCSI 共享存储 --centos 7.4 作为target
    Cannot open the disk '/vmfs/volumes/5e97f429-a56d6ea0-1ef3-000c29a09445/oracle_node1/oracle_node1_1.vmdk' or one of the snapshot disks it depends on.
    RabbitMQ windows2016 镜像模式 haproxy+keepalived
  • 原文地址:https://www.cnblogs.com/RunForLove/p/5100009.html
Copyright © 2011-2022 走看看