从 SQL 服务器 table 获取随机行数

Get random number of rows from SQL Server table

我正在尝试使用快速方法从大型 table(超过 100 万行)中获取 5 个随机行数。

到目前为止,我已经用这些 SQL 查询测试了:

方法一

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

此方法估计 I/O 成本是 0.0127546 所以这非常快(非集群索引扫描)

方法二

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

此方法的排序估计 I/O 成本为 117.21189,索引扫描非聚集估计 I/O 成本为 2.8735,因此这会影响性能

方法三

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

此方法的排序估计 I/O 成本为 117.212,索引扫描非聚集估计 I/O 成本为 213.149,此查询比所有查询都慢,因为估计子树成本为213.228 所以它很慢。

更新:

方法四

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-to-SQL?谢谢

如前所述 Here 最好的方法是:

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

如果您想将方法 2 转换为 Linq To Entities,只需使用 jitender 回答的解决方案,如下所示:

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

但是对于方法 1,它在您的基准测试之后非常快,您需要执行以下 C# 代码,因为 Linq To Entities 没有对应的 LINQ SQL 语句 TABLESAMPLE(1000 rows).

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

您可以将 SQL 语句移动到 SQL 视图或存储过程中,它将接收要接收的客户数量。

更新

对于似乎非常快的方法 4(始终遵循您的基准),您可以执行以下 Linq To Entities:

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

Entity Framework可以翻译成SQL定义成SqlFunctionsclass的所有函数。在这些函数中,我们有 Checksum 函数,它将执行您想要的操作。

如果您想加入其他表,您可以使用 Linq To Entites 轻松完成,所以我只是通过仅查询 Customers DbSets.

来简化我的版本