2017-05-08 82 views
5

我想用一個快速方法從一個大表(超過100萬行)中獲得5個隨機數的行。從SQL Server表中獲取隨機行數

到目前爲止,我所與這些SQL查詢測試:

方法1

Select top 5 customer_id, customer_name 
from Customer TABLESAMPLE(1000 rows) 
order by newid() 

這種方法估計I/O成本爲0.0127546,所以這是非常快的(索引掃描非聚集)

方法2

select top 5 customer_id, customer_name 
from Customer 
order by newid() 

這種方法的排序估計I/O成本117.21189和索引掃描非聚集估計I/O成本2.8735,所以這是影響性能

方法3

select top 5 customer_id, customer_name 
from Customer 
order by rand(checksum(*)) 

這種方法的排序估計I/O成本爲117.212,而且索引掃描非集羣估計I/O成本爲213.149,此查詢比全部要慢,因爲估計的子樹成本爲213.228,所以速度非常慢。

UPDATE:

方法4

select top 5 customer_id, customer_name, product_id 
from Customer 
Join Product on product_id = product_id 
where (customer_active = 'TRUE') 
order by checksum(newid()) 

這種做法更好,速度非常快。所有的基準測試都很好。

問題

我如何轉換方法4到LINQ到SQL?由於

+0

您是否在詢問有關提高隨機查詢性能或將查詢轉換爲LINQ的問題? –

+0

你想要結果如何隨機? 'TABLESAMPLE'實際上並不是隨機的(除非你的行很大,只有一行適合頁面)。 –

+0

@JuanCarlosOropeza是的首先,我正在尋找轉換方法1到LINQ,如果不可能的話,那麼我正在尋找更好的方法。 –

回答

2

如果你想2轉換方法爲LINQ到實體只使用由jitender回答瞭解決方案,它看起來像這樣:

var randomCoustmers = context.Customers.OrderBy(x => Guid.NewGuid()).Take(5); 

但是對於方法1這是你的基準測試後非常快,你需要做以下的C#代碼be導致Linq To Entities對於此SQL語句TABLESAMPLE(1000 rows)沒有LINQ等效項。

var randomCoustmers = context.Customers.SqlQuery("Select TOP 5 customer_id, customer_name from Customer TABLESAMPLE(1000 rows) order by newid()").ToList(); 

您可以將SQL語句到一個SQL視圖或存儲過程將接收客戶採取的數量。

UPDATE

對於方法4這似乎是非常快的(總是按照你的基準),你可以做以下的LINQ到實體:

var randomCoustmers = context.Customers.OrderBy(c => SqlFunctions.Checksum(Guid.NewGuid()).Take(5); 

實體框架可以翻譯轉換爲SQL定義爲SqlFunctions類的所有函數。在這些功能我們有Checksum功能,它會做你想做的。

如果你想加入其他表格,你可以毫不費力地使用Linq To Entites,所以我只通過查詢CustomersDbSets來簡化我的版本。

+0

我要去測試它,同時我已經更新了這個問題,請你檢查一下。謝謝 –

+0

@ArbazAbid我更新了我的答案。 – CodeNotFound

+0

非常感謝。使用SqlFunctions的方法4像魅力一樣工作。服務器上非常流暢且無負載。再次感謝:) –

0

如前所述 Here的最好的方式:

var randomCoustmers = Customers.OrderBy(x => Guid.NewGuid()).Take(5); 
+2

在這種情況下,更好地使用「重複問題」關閉選項 –

+0

您可以根據OP的預期轉換**方法2 **而不是**方法1 **。 – CodeNotFound

+0

其實我已經在使用它,但I/O的成本非常高,所以它會影響性能。 **方法2 **是一樣的。我正在尋找更好的方法。 –