2010-03-15 36 views
1

我有一個數據表可搜索和排序,但可能會產生數百或數千個廣泛搜索結果。假設爲「foo」的用戶搜索和按降序價格秩序的FOOS我想表現出快速跳轉選擇菜單,如下所示:如何在分頁中爲每個頁面拉出和顯示範圍(最小 - 最大)數據?

<option value="1">Page 1 ($25,000,000 - $1,625,000)</option> 
<option value="2">Page 2 ($1,600,000 - $1,095,000)</option> 
<option value="3">Page 3 ($1,095,000 - $815,000)</option> 
<option value="4">Page 4 ($799,900 - $699,000)</option> 
... 

有直接查詢這些信息的有效途徑數據庫?我一直在抓取所有匹配的記錄,並使用PHP來計算每個頁面的最小值和最大值,這些值似乎效率低下並可能導致縮放問題。

我已經能夠想出的唯一可能的技術是使計算變量可以將每個X記錄(X記錄到頁面)遞增,按此分組,併爲每個頁面選擇MIN/MAX分組......不幸的是,我還沒有能夠想出一種方法來生成該變量。

回答

2

儘管技術上可能,我建議你不要浪費時間使用此功能,並尋找另一種方法。

首先,一些關於分頁的背景資料。分頁通常使用ORDER BY ... LIMIT [offset], [rows]完成。爲了讓MySQL爲您提供給定偏移量的行,它必須讀取全部先前的行然後將其丟棄。這是昂貴的並且成本隨着抵消增加而增加。 (例如,限制1000,20必須讀取1020行然後丟棄1000)。當使用索引無法完成ORDER BY時,情況更糟糕。這可導致在整個無限結果集被讀取,然後filesorted和然後前1000行被扔掉以滿足LIMIT 1000, 20

現在,讓我們來解決您的具體問題。如圖所示,分頁不是什麼「神奇」的東西;這是對結果集進行分頁的一種相當強悍的方式。具體而言,您不知道事先在什麼頁面上進行排序而不對整個結果集進行排序。要計算出每頁最小值和最大值,您需要使用臨時表,然後根據此臨時表計算整個結果集的每頁最小/最大值。如果你的數據是不穩定的,那麼你需要重新計算這個數據,就像底層數據發生變化一樣。

如果存儲引擎在某種程度上保存什麼「頁面」各行對一個給定的順序,那麼你可以做到這一點相對容易。不幸的是,事實並非如此。

此外,我會質疑你的方法對你的用戶的有用性。你的例子顯示了一個很好的價格分佈。你能確定你不會像以下這樣的範圍?

<option value="1">Page 1 ($1,005,000 - $1,004,000)</option> 
<option value="2">Page 2 ($1,004,000 - $1,003,450)</option> 
<option value="3">Page 3 ($1,003,450 - $1,003,387)</option> 
<option value="4">Page 4 ($1,003,387 - $1,003,342)</option> 

我會懷疑這是否會給用戶帶來任何好處。

建議

  • 讓您的分頁簡單
  • 如果你希望用戶能夠選擇的價格範圍,然後建立在作爲一個過濾器 - 不與分頁結合起來。

搜索亞馬遜的東西,注意他們的結果頁面。你會得到你的搜索結果簡單分頁。在左側,您將有多種過濾器應用於您的搜索以進一步優化。

+0

是的,這基本上是我要來的結論......只是不知道我是否錯過了一些聰明的東西,這會使它很好地工作。 FWIW我在查詢中熟悉LIMIT/OFFSET,它目前沒有被使用的唯一原因是因爲我們不得不查看PHP結果中的每一行來創建每頁的最小/最大值。儘管如此,如果MySQL必須查看第一個X匹配來抵消它們,是不是每次都返回所有內容並逐步遍歷PHP中的集合呢? – 2010-03-15 17:13:57

+0

@Ty:是的。 PHP所做的任何事情,MySQL(C)的速度都提高了10-100倍。 – hobodave 2010-03-15 17:16:36

+0

@Ty:分頁優化資源:http://www.percona.com/ppc2009/PPC2009_mysql_pagination.pdf – hobodave 2010-03-15 17:17:22

相關問題