2017-05-08 80 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 **是一样的。我正在寻找更好的方法。 –