2010-08-24 106 views
6

在一個站點上顯示一個包含約70K條記錄的表格,每頁顯示50條記錄。 在查詢上使用limit offset,50完成分頁,並且記錄可以在不同的列上排序。選擇最新記錄時選擇速度要慢很多

瀏覽最新的頁面(因此偏移約60,000)使得查詢慢得多瀏覽前幾頁(約10倍)

這是使用limit命令的一個問題,當比? 是否有其他方法可以獲得相同的結果?

+0

好問題,我不熟悉MySQL在這方面的工作原理。 – RedFilter 2010-08-24 14:26:05

+0

感謝你的回覆,稍後會測試它,希望能獲得一些速度。 – Omiod 2010-08-24 16:07:28

回答

7

隨着較大的偏移量,MySQL需要瀏覽更多的記錄。

即使計劃使用filesort(這意味着所有的記錄應該瀏覽),MySQL優化,這樣只有$offset + $limit最高記錄進行排序,這使得它更加高效爲$offset較低值。

典型的解決方案是索引您訂購的列,記錄列的最後一個值,並在隨後的查詢重用,像這樣:

SELECT * 
FROM mytable 
ORDER BY 
     value, id 
LIMIT 0, 10 

,輸出:

value id 

1  234 
3  57 
4  186 
5  457 
6  367 
8  681 
10  366 
13  26 
15  765 
17  345 -- this is the last one 

要進入下一個頁面,你可以使用:

SELECT * 
FROM mytable 
WHERE (value, id) > (17, 345) 
ORDER BY 
     value, id 
LIMIT 0, 10 

,它採用了在請登錄(value, id)查詢。

當然這不會對任意訪問頁面有所幫助,但有助於順序瀏覽。

另外,MySQL在後期查詢中存在一些問題。如果列索引,它可能是值得嘗試重寫查詢是這樣的:

SELECT * 
FROM (
     SELECT id 
     FROM mytable 
     ORDER BY 
       value, id 
     LIMIT $offset, $limit 
     ) q 
JOIN mytable m 
ON  m.id = q.id 

請參閱這篇文章更詳細的解釋:

+0

MySQL支持元組式樣的語法('(val1,val2)>(1,2)')?我以前從來沒有見過。什麼是組合器(和,我假設)?我想你每天都會學到新的東西...... – ircmaxell 2010-08-24 14:40:41

+0

@ircmaxell:是的。它是字典順序,與val1> 1 OR(val1 = 1 AND val2> 2)相同' – Quassnoi 2010-08-24 14:42:19

+0

好的答案。這裏是一個演示,我認爲有一些很好的信息是沿着相同的路線:http://www.slideshare.net/Eweaver/efficient-pagination-using-mysql – nathan 2010-08-24 18:42:01

2

這是MySQL如何處理限制。如果它可以對索引進行排序(並且查詢足夠簡單),則可以在找到第一個offset + limit行後停止搜索。所以LIMIT 0,10意味着如果查詢很簡單,它可能只需要掃描10行。但LIMIT 1000,10意味着至少需要掃描1010行。當然,需要掃描的實際行數取決於許多其他因素。但重點在於,limit + offset越低,需要掃描的行數越低...

至於變通方法,我會優化您的查詢,以便查詢本身沒有LIMIT子句儘可能高效。 EXPLAIN是你在這種情況下的朋友...