2013-10-03 34 views
3

早上好,MySQL基於特定訂單分頁大數據

我有一張表,其中包含幾百萬行,我需要查看TimeStamp訂購的數據。

,當我試圖做到這一點

SELECT * FROM table ORDER BY date DESC offset 0 LIMIT 200 

MySQL的將責令所有數據,然後將響應與200行,這是一個性能問題。因爲每次我想滾動頁面時都不明智地命令所有內容!

你對我們如何提高性能有什麼想法嗎?

+0

你會澄清爲什麼'抵消0'? – 7alhashmi

+0

是否將記錄始終按時間順序添加到表中?在這種情況下,只需在表中添加一個自動增量整數列「RowNumber」,向其中添加一個索引,並使用WHERE RowNumber BETWEEN 0 AND 200'。 – Dan

+0

@ 7alhashmi 0只是一個變量的例子,它可能是任何東西!它是一個尋呼系統! – daigoor

回答

3

首先你需要根據日期字段創建一個索引。這允許按順序檢索行,而不必在每次發出請求時都對整個表進行排序。其次,基於索引的分頁越深入研究結果集越慢。舉例說明:

  • ORDER BY indexedcolumn LIMIT 0, 200非常快,因爲它只需掃描200行索引。

  • ORDER BY indexedcolumn LIMIT 200, 200是比較快的,但需要掃描400行索引。

  • ORDER BY indexedcolumn LIMIT 660000, 200非常慢,因爲它需要掃描660,200行索引。

    注意:即使如此,這仍然可能比根本沒有索引快得多。

你可以用幾種不同的方法解決這個問題。

  1. 實現基於價值的分頁,所以你基於以前的頁面上的最後結果的值分頁。例如:

    WHERE indexedcolumn>[lastval] ORDER BY indexedcolumn LIMIT 200將[lastval]替換爲當前頁面的最後結果的值。索引允許隨機訪問特定值,並從該值向前或向後進行。

  2. 只允許用戶查看第一個X行(例如1000)。如果他們想要的價值是第2529個價值,那麼這是不好的。

  3. 想象一下,打破你的大表的邏輯方式,例如第一個字母,年份等,所以用戶不需要遇到整個數百萬行的結果集,而是需要鑽取到首先是一個特定的子集,這將是一個較小的集合,並且可以更快地進行排序。

如果您將WHERE和ORDER BY組合在一起,您需要在索引設計中反映這一點,以使MySQL繼續受益於排序索引。例如,如果您的查詢是:

SELECT * FROM mytable WHERE year='2012' ORDER BY date LIMIT 0, 200 

然後您的索引需要按照該順序在兩列(年份,日期)上。

如果您的查詢是:

SELECT * FROM mytable WHERE firstletter='P' ORDER BY date LIMIT 0, 200 

然後索引將需要在該順序兩列(firstletter,日期)。

想法是,只要您在條件中指定以前的列爲常量(單個值),多列上的索引就允許按任意列進行排序。因此,如果在WHERE條件中指定A和B爲常量,則A,B,C,D和E上的索引允許按C排序。 A和B不能是範圍。

+0

它看起來像這是唯一的解決方案,但我可以使用它,因爲我沒有訪問數據庫!如果您無法訪問數據庫或者甚至無法訪問數據庫,與某些客戶合作非常困難!我甚至嘗試創建一個虛擬數據庫並在其中導入數據,但該解決方案不適用於客戶端,因此我們放棄了該功能! ...儘可能簡單:) – daigoor

+0

@thomasrutter:謝謝你的解釋。一個簡單的問題:當value是時間戳時我們如何使用基於值的分頁,並且我們可以在不同的行中使用相同的時間戳值 - >在這種情況下,LIMIT子句會產生問題。 – j10

+0

它必須在獨特的列或列組合上完成。如果訂單永遠不會改變(即無法修改時間戳),那麼請考慮使用自動增量ID並僅對該列進行排序。或者,您可以在多個列上排序,例如'ORDER by timestamp DESC,unique_ID DESC',以便在發生時間戳衝突時按ID排序。你需要通過兩個增值稅。 – thomasrutter