2010-02-23 70 views
5

好吧,100K行以隨機順序返回,沒有SQL超時請

我已經做了很多的閱讀返回隨機行去年成立,我們想出瞭解決方案是

ORDER BY newid() 

這對於< 5k行很好。但是,當我們獲得> 10-20k行時,我們正在獲取SQL超時,計劃執行計劃告訴我,我的查詢成本中有76%來自此行。當我們有大量的行時,刪除這條線會使速度增加一個數量級。

我們的用戶有這樣的要求,一次做多達100K行。

給你更多的細節。

我們有一張有260萬個4位字母數字代碼的表格。我們隨機使用這些來獲得進入場地的權限。例如,如果我們有一個容量爲5000的事件,則隨機抽取5000個這樣的數據,然後將其作爲條形碼發送給每個客戶,然後在門口的條形碼掃描應用程序同樣的列表是5000.使用4位字母數字代碼(而不是像GUID那樣的一個愚蠢的長數字)的原因是人們很容易寫下數字(或將它短信給朋友),只需將號碼並手動輸入,所以我們不需要大量的字符。客戶喜歡最後一點btw。

有沒有比ORDER BY newid()更好的方法,還是有更快的方式從2.6米的表中獲得100k隨機行?

哦,我們使用的是MS SQL 2005

感謝,

+0

一個有趣的閱讀這裏:http://www.sqlteam.com/article/returning-rows-in-random-order-part-ii-revenge-of-the-randomizer – 2010-02-23 23:59:31

回答

3

如果你想生成隨機4位數代碼,爲什麼不直接產生它們,而不是試圖拉他們出了一個數據庫?

從0到1,679,616(這是唯一的四位數字的字母數字代碼的數量,忽略大小寫--260萬行必須有一些重複項)生成100k個唯一數字,並將它們轉換爲您的四位數代碼。

0

正如感興趣的事,是什麼,如果你通過

ORDER BY CHECKSUM(newid()) 
0

一個想法取代

ORDER BY newid() 

像性能的過程分解成步驟。在表中爲GUID添加一列,然後在添加GUID的表中執行更新語句。如有必要,可以提前完成。然後,您應該能夠使用GUID列上的orderby運行查詢,以相同的方式接收結果。

7

有一篇名爲「Selecting Rows Randomly from a Large Table」的MSDN文章,講述了這個確切的問題,並展示了一個解決方案(不使用排序,而是在生成的列上使用WHERE子句來過濾行)。

您的查詢速度較慢的原因是ORDER BY子句會導致將整個表複製到tempdb中進行排序。

1

您不必排序。

DECLARE @RandomNumber int 
DECLARE @Threshold float 
SELECT @RandomNumber = COUNT(*) FROM customers 
SELECT @Threshold = 50000/@RandomNumber 

SELECT TOP 50000 * FROM customers WHERE rand() > @Threshold ORDER BY newid() 
+0

你仍然排序,因爲你有' ORDER BY newid()'在你的查詢中。 – adrianbanks 2010-02-24 00:26:34

+0

但我只排序約50k,而不是整個表。如果我們用rand()選擇超過50k,我們必須放棄它們。但是,如果我們只是在沒有排序的情況下進入TOP,那麼名單上的第一人將會享有特權。 – user76035 2010-02-24 00:35:12

0

您是否曾嘗試在給定的int列上使用%(modulo)?不知道你的表結構是什麼,但你可以做這樣的事情:

從your_table 選擇頂部50000 * 其中CAST((CAST(ASCII(SUBSTRING(venuecode,1,1))爲varchar(3) )+ CAST(ASCII(SUBSTRING(venuecode,2,1))as varchar(3))+ CAST(ASCII(SUBSTRING(venuecode,3,1))as varchar(3))+ CAST(ASCII(SUBSTRING (venuecode,4,1))as varchar(3)))as bigint)介於0和50000之間的%500000

上述代碼會將所有字母數字場地轉換爲整數,然後將整個表格放入500,000個桶中,其中您將採用介於0和50000之間的前50000.您可以p (500,000)後的數字與之後的數字一致,並且可以與之間玩。這應該隨機爲你。不確定在哪裏條款會咬你的表現,但它是值得一試。另外,如果沒有訂單,訂單就沒有保證(如果您有多個cpus和線程)。