为爱奔跑


无论在家出家。必须上敬下和。忍人所不能忍。行人所不能行。代人之劳。成人之美。静坐长思己过。闲谈不论人非。行住坐卧。穿衣吃饭。从幕至朝。一名佛号。不令间断。或小声念。或默念。除念佛外。不起别念。若或妄念一起。当下就要教他消灭。当生惭愧心及忏悔心。从有修持。总觉我工夫很浅。不自矜夸。只管自家。不管人家。只看好样子。不看坏样子。看一切人都是菩萨。唯我一人是凡夫!

  我们做的后端项目一般都会有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

 

 

 

 

 

 

posted on 2016-01-04 19:24  RunforLove  阅读(4120)  评论(0编辑  收藏  举报