2011-08-02 99 views
2

我已經RAND()和它的性能問題,閱讀有關訂單 - 做這些只適用於返回大數據集的查詢?舉例來說,如果我有10萬行的表,並且使用WHERE子句返回10條記錄的數據集,然後使用ORDER BY RAND()LIMIT 1,經過我的表已經滲透到將這個ORDER BY RAND()被應用記錄匹配WHERE子句,因此具有可忽略的性能問題?MySQL ORDER BY RAND()函數何時排序?

+0

幾乎任何東西可以很快去的時候只能用小數據集進行操作,但在概念上一個LIMIT ORDER BY子句後適用。所以它取決於查詢優化器。爲什麼不試試一個測試數據庫? –

+0

請參閱下面的實驗 - 將ORDER BY RAND()應用於WHERE子句返回的記錄的子集 - 對於返回143條記錄的記錄集,限制爲隨機記錄的時間可以忽略不計,而應用它對整個表沒有where子句花費了更多的時間。 – key2starz

回答

8

你說得對,它會與WHERE,GROUP BY減少的行數和HAVING後應用ORDER BY。但它會在LIMIT之前應用ORDER BY。

因此,如果您篩選的行數下降充分,那麼,在ORDER BY RAND()可以達到你想要的東西沒有一個偉大的業績影響。代碼的合法利益很簡單,易於閱讀。

當您的認爲您的查詢應該將行數減少到某個較小值時,就會出現問題,但隨着數據量的增長,需要排序的行數再次變大。由於您的查詢,則不會對排序結果LIMIT 10隱藏,你BY RAND()上的50萬行執行訂單的事實。你只是看到神祕的表現越來越糟。

我已經寫了有關替代方法在我的書SQL Antipatterns: Avoiding the Pitfalls of Database Programming,或在這裏其他的答案對堆棧溢出選擇一個隨機行:

+0

另外兩張海報與您的答案相矛盾,並表示無論WHERE子句如何,它都會爲表格中的所有行生成隨機數字;根據我自己的測試,你的答案是正確的答案。謝謝!在我的情況下,我需要一個來自數據庫表的一小部分的隨機行。 – key2starz

+0

條例草案,如果你閱讀這個,我讀了關於你的2查詢技術在這裏:http://stackoverflow.com/questions/3558665/randomizing-large-dataset/3558919#3558919在我的情況下,我需要使用多個查詢加入等等。這種技術在這種情況下也能起作用嗎? – key2starz

0

RAND()值將針對每一行進行計算,因此對於大型數據集不是非常有效,LIMIT子句不會更改該值。要解決這個通常的方法是計算提前一個隨機數,然後檢索基於一些預生成索引列與之對應的行。

這裏有一個詳細的解釋:

http://jan.kneschke.de/projects/mysql/order-by-rand/

2

不要緊,你有多少行選擇。如果ORDER BY RAND()爲表中的每一行計算一個隨機數。這是因爲它必須計算每一行的隨機值才能知道哪一行產生了最大的值。所以,如果你有10萬行的表,然後調用ORDER BY RAND() LIMIT 1你告訴MySQL來產生一個隨機數爲100,000行,由數排序,然後給你的第一個。

這是很要快得多:從Table

    1. SELECT COUNT(*)生成的腳本/編程語言0和上面的查詢結果減去1之間的隨機數。

    2. SELECT * FROM Table LIMIT random_number_here,1

  • 1

    基於快速測試,我必須得出結論,ORDER BY RAND()僅適用於應用WHERE語句,而不是整個數據集。從表中

    結果與50,000行:

    SELECT * FROM `mytable` LIMIT 1 (1 total, Query took 0.0007 sec) 
    SELECT * FROM `mytable` WHERE First = 'Hilda' LIMIT 1 (1 total, Query took 0.0010 sec) 
    SELECT * FROM `mytable` WHERE First = 'Hilda' (142 total, Query took 0.0201 sec) 
    SELECT * FROM `mytable` WHERE First = 'Hilda' ORDER BY RAND() LIMIT 1 (1 total, Query took 0.0229 sec) 
    SELECT * FROM `mytable` WHERE First = 'Hilda' ORDER BY RAND() (142 total, Query took 0.0236 sec) 
    SELECT * FROM `mytable` ORDER BY RAND() LIMIT 1 (1 total, Query took 0.4224 sec)