程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> 關於MYSQL數據庫 >> 在MySQL中使用LIMIT進行分頁的方法

在MySQL中使用LIMIT進行分頁的方法

編輯:關於MYSQL數據庫

今天看一個水友說他的MySQL現在變的很慢。問什麼情況時。說單表超過2個G的一個MyISAM。真垃圾的回答方式。

    簡單答復:換一個強勁的服務器。換服務器很管用的:)

………
       最終讓取到慢查詢:
 

  SELECT * FROM pw_gbook WHERE uid='N' ORDER BY postdate DESC LIMIT N,N;
 
  SELECT * FROM pw_gbook WHERE uid='N' ORDER BY postdate DESC LIMIT N,N;

如:
   

SELECT * FROM pw_gbook WHERE uid='48' ORDER BY postdate DESC LIMIT 1275480,20;
 
  SELECT * FROM pw_gbook WHERE uid='48' ORDER BY postdate DESC LIMIT 1275480,20;

        看到這個語句我都吐血了(BT的PHPWIND分頁啊,這個語句是PHP初學者寫出來的還正常,但PHPWIND那麼成熟的社區了還有這樣的問題)。
        我這裡簡單說一下LIMIT的原理。這裡以LIMIT N,M為基礎:LIMIT首先要找查N+M行,然後從N行處,取M行。那麼這樣的SQL對一次查詢1275500一個操作應該是一個昂貴的開銷。對於LIMIT這類的優化,第一個目標就是讓N變的盡可能的小或是不用。
     怎麼才能使這個N盡可能小呢。我們能做的其實就是用相對的值,給分頁一個提示。如現在我們看的是第5頁,看完看想看第6頁,第6頁同樣顯示是20條記錄。我們就可以想到,以這個例子為准:我們可以肯定的是第6頁的日值應小於第5頁的,如果第5頁的最小日值為:2009-11-4,那我們就可以用:
    

SELECT * FROM pw_gbook WHERE uid='48' and postdate<'2009-11-1' ORDER BY postdate DESC LIMIT 20;
 
   SELECT * FROM pw_gbook WHERE uid='48' and postdate<'2009-11-1' ORDER BY postdate DESC LIMIT 20;

這樣來查詢第6頁的內容。同樣對於查看第4頁的內容(假設第5頁的最大日期為:2009-11-3)則第4頁的內容為:
 

  SELECT * FROM pw_gbook WHERE uid='48' and postdate>'2009-11-3' ORDER BY postdate DESC LIMIT 20;


   SELECT * FROM pw_gbook WHERE uid='48' and postdate>'2009-11-3' ORDER BY postdate DESC LIMIT 20;

         這是一個基本的思想。接下來討論一下怎麼展現的問題。

         再說一下這種業務的SQL怎麼實現:對於分頁的展示可以用多用類型。這裡說三種常用的類型:

第一種:顯示“上一頁” “下一頁”這種類型

         這種方式相對簡單也就出現了我們看到那種SQL不思考的寫法。合理的做法:

         第一頁:
     

SELECT * FROM pw_gbook WHERE uid='48' ORDER BY postdate DESC LIMIT 20;
 
   SELECT * FROM pw_gbook WHERE uid='48' ORDER BY postdate DESC LIMIT 20;

         第二頁:根據第一頁的postdate進行查詢如:
      SELECT * FROM pw_gbook WHERE uid='48'  and postdate<'2009-11-3'  ORDER BY postdate DESC LIMIT  20;
 
      SELECT * FROM pw_gbook WHERE uid='48'  and postdate<'2009-11-3'  ORDER BY postdate DESC LIMIT  20;

         為什麼說這個簡單呢,這個不存在跳頁的問題。接下來這種就存在一個跳頁的問題了。

第二種:顯示 “ 1,2,3,4,5…”

         第一頁: 還是以第一頁的方式實現:
        

 SELECT * FROM pw_gbook WHERE uid='48' ORDER BY postdate DESC LIMIT 20;
 
     SELECT * FROM pw_gbook WHERE uid='48' ORDER BY postdate DESC LIMIT 20;

         第二頁:和原來一樣。如果跳頁,如從第二頁跳到第5頁,這裡有一個第二頁的最小日期為:2009-11-3(假設值,可以由第二頁的程序查詢得到),第二到第5,差2頁,每頁20條記錄,那麼就可以用:

SELECT * FROM pw_gbook WHERE uid='48' and postdate<'2009-11-3' ORDER BY postdate DESC LIMIT 40,20;


SELECT * FROM pw_gbook WHERE uid='48' and postdate<'2009-11-3' ORDER BY postdate DESC LIMIT 40,20;

        看到這裡明白為什麼大型網站的分頁不是一下標識出來完了,讓都能點了吧。也不會給你一個框讓你輸入一個頁跳過去了。如果跳的頁面過多,也就存在N值過大的問題了。所以要想辦法必免。

第三種:顯示 “1,2,3,4,5,…. 末頁” 或是 “首頁,<<100,101,102,103 >>末頁”

這裡有一個特殊的一地方:

別的頁面的跳轉的上面一樣。這裡就加一個末頁,這裡又分兩種情況,如果知道最後一頁是多少頁,也就知道了前一頁的最小日期(分頁提示值),這樣就可以用上面的方法查看最後一頁的內容(會出現不足20條的現象),另一種,我就不知道最後是第幾頁,我就是想看看最後什麼樣子,那麼就可以用(一定是顯示20條):

SELECT * FROM pw_gbook WHERE uid='48' ORDER BY postdate ASC limit 20;
 
SELECT * FROM pw_gbook WHERE uid='48' ORDER BY postdate ASC limit 20;

         首頁這裡就不在說了。

       

         具體怎麼實現搞明白了,就可以做PHP代碼的修改了。稍稍修改一下,就會帶來意想不到的效果。

 

這裡只是一個通用的分頁處理方法。不同的業務有可能還有不同的方法處理。如果在條件可能和情況可以考用:between … and .. 帶代替limit分頁操作。

第三種方法:       
簡單的邏輯轉換。
  

SELECT * FROM pw_gbook WHERE uid='48' ORDER BY postdate DESC LIMIT 1275480,20;
 
  SELECT * FROM pw_gbook WHERE uid='48' ORDER BY postdate DESC LIMIT 1275480,20;

轉換成:
  

SELECT * FROM pw_gbook WHERE id>1275480 and uid='48' ORDER BY postdate DESC LIMIT 20;
 
  SELECT * FROM pw_gbook WHERE id>1275480 and uid='48' ORDER BY postdate DESC LIMIT 20;

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved