Sql server 以随机顺序返回100k行,没有SQL超时,请

Sql server 以随机顺序返回100k行,没有SQL超时,请,sql-server,sql-server-2005,random,Sql Server,Sql Server 2005,Random,嗯 去年我读了很多关于返回随机行集的书,我们想出的解决方案是 ORDER BY newid() 这对于10-20k行来说是很好的,因为我们得到了SQL超时,计划的执行告诉我76%的查询成本来自这一行。当我们有大量的行时,去掉这条线会使速度提高一个数量级 我们的用户有这样一个要求:一次最多做10万行 给你们更多的细节 我们有一个包含260万个4位字母数字代码的表。我们使用一组随机的这些来进入一个场地。例如,如果我们有一个容量为5000的活动,将从表中随机抽取5000个,然后作为条形码发送给每个客

去年我读了很多关于返回随机行集的书,我们想出的解决方案是

ORDER BY newid()
这对于10-20k行来说是很好的,因为我们得到了SQL超时,计划的执行告诉我76%的查询成本来自这一行。当我们有大量的行时,去掉这条线会使速度提高一个数量级

我们的用户有这样一个要求:一次最多做10万行

给你们更多的细节

我们有一个包含260万个4位字母数字代码的表。我们使用一组随机的这些来进入一个场地。例如,如果我们有一个容量为5000的活动,将从表中随机抽取5000个,然后作为条形码发送给每个客户,然后门口的条形码扫描应用程序将具有相同的5000个列表。使用4位字母数字代码(而不是像GUID那样的长得愚蠢的数字)的原因是,人们很容易记下数字(或发短信给朋友),只需携带数字并手动输入,因此我们不需要大量字符。顺便说一句,顾客喜欢最后一点

有没有比按newid()排序更好的方法,或者有没有更快的方法从一个有2.6 mil的表中获取100k个随机行

哦,我们正在使用MS SQL 2005

谢谢


Jo

如果要生成随机的4位代码,为什么不直接生成它们,而不是尝试从数据库中提取它们


生成从0到1679616的100k唯一数字(这是唯一的四位字母数字代码的数量,忽略大小写-260万行必须有一些重复项)并将其转换为四位代码。

有趣的是,如果替换

ORDER BY newid()


一个想法是将过程分解为多个步骤。在表中为GUID添加一列,然后在表中执行update语句添加GUID。如有必要,可提前完成。然后,您应该能够使用GUID列上的orderby运行查询,以相同的方式接收结果

有一篇题为“”的MSDN文章讨论了这个问题,并给出了一个解决方案(不使用排序,而是在生成的列上使用WHERE子句来过滤行)


查询速度慢的原因是,
orderby
子句导致将整个表复制到tempdb中进行排序。

您不必排序

 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()
你试过在给定的int列上使用%(模)吗?不确定您的表结构是什么,但您可以这样做:

选择前50000名* 从你的桌子上 其中CAST((CAST(ASCII(子字符串(venuecode,1,1))为varchar(3))+ 强制转换(ASCII(子字符串(venuecode,2,1))为varchar(3))+ 强制转换(ASCII(子字符串(venuecode,3,1))为varchar(3))+ 将(ASCII(子字符串(venuecode,4,1))转换为varchar(3)))转换为bigint)%500000,介于0和50000之间


上面的代码将获取所有字母数字区域,并将它们转换为整数,然后将整个表拆分为500000个存储桶,其中您将获取介于0和50000之间的前50000个存储桶。您可以使用%since(500000)之后的数字,也可以使用介于两者之间的数字。这将为您随机选择它。不确定where子句是否会影响性能,但值得一试。此外,如果没有order by,则无法保证顺序(如果您有多个CPU和线程)。

这里有一篇有趣的文章:您仍然在排序,因为您的查询中有
order by newid()
。但我只对ca 50k进行排序,而不是对整个表进行排序。问题是,如果我们使用rand()选择的值超过50k,我们就必须删除它们。但是,如果我们不进行排序就获得了榜首,排名第一的人将享有特权。
 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()