从 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
.
来简化我的版本
我正在尝试使用快速方法从大型 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
.