【问题标题】:Select random sampling from sqlserver quickly快速从sqlserver中选择随机抽样
【发布时间】:2010-10-13 17:12:14
【问题描述】:

我有一个超过 1000 万行的大表。我需要有效地从中获取 5000 个随机样本。我有一些约束将我正在寻找的总行数减少到 9 百万。

我尝试通过 NEWID() 使用 order,但该查询将花费太长时间,因为它必须对所有行进行表扫描。

有没有更快的方法来做到这一点?

【问题讨论】:

  • 你在使用一些 php/asp/ 类似的东西吗?
  • 这有什么关系?我当然不希望应用层这样做!

标签: sql sql-server database performance random


【解决方案1】:

如果您可以使用伪随机抽样并且您使用的是 SQL Server 2005/2008,那么请查看 TABLESAMPLE。例如,SQL Server 2008 / AdventureWorks 2008 中的一个基于行的示例:

USE AdventureWorks2008; 
GO 


SELECT FirstName, LastName
FROM Person.Person 
TABLESAMPLE (100 ROWS)
WHERE EmailPromotion = 2;

问题是 TABLESAMPLE 并不是完全随机的,因为它从每个物理页面生成给定数量的行。除非您也限制了 TOP,否则您可能无法准确返回 5000 行。如果您使用的是 SQL Server 2000,您将不得不生成一个与主键匹配的临时表,或者您将不得不使用使用 NEWID() 的方法来完成。

【讨论】:

  • 错了,tablesample 的工作原理是选择适当数量的页面,然后返回在这些页面上找到的所有行。重点是避免击中所有放置表格的页面。
  • 对不起,你是对的。读错算法。它确定行数,然后选择整个页面或不获取近似值。
  • 旁注:您正在对已截断的样本应用 where 子句。所以不要指望它在所有情况下都返回匹配的行。
【解决方案2】:

您是否考虑过使用 TABLESAMPLE 子句?

例如:

select *
from HumanResources.Department tablesample (5 percent)

【讨论】:

  • 这个问题太乱了,微软不得不做出这个原生的 TABLESAMPLE 实现,它是所有场景中最稳定和最高效的
【解决方案3】:

SQL Server 2000 解决方案,关于 Microsoft(而不是大型表上的慢 NEWID()):

SELECT * FROM Table1
WHERE (ABS(CAST(
 (BINARY_CHECKSUM(*) *
  RAND()) as int)) % 100) < 10

Microsoft 的 SQL Server 团队意识到无法将 很容易随机抽取行样本是 SQL Server 2000 中的一个常见问题; 因此,该团队在 SQL Server 2005 中通过引入 TABLESAMPLE 子句。此子句通过以下方式选择行的子集 选择随机数据页并返回这些数据页上的所有行 页。但是,对于我们这些仍然拥有可以运行的产品的人来说 SQL Server 2000 并且需要向后兼容,或者谁真正需要 行级随机性,BINARY_CHECKSUM 查询非常有效 解决方法。

解释可以在这里找到: http://msdn.microsoft.com/en-us/library/cc441928.aspx

【讨论】:

    【解决方案4】:

    是的,tablesample 是您的朋友(请注意,它在统计意义上不是随机的): Tablesample at msdn

    【讨论】:

    • 我们使用的是sqlserver 2005,但是我们的数据库兼容级别是80,所以没有tablesample。 :(还有其他想法吗?
    • select * from customers order by newid()
    猜你喜欢
    • 1970-01-01
    • 2016-04-27
    • 2011-07-14
    • 2010-09-17
    • 2011-05-18
    相关资源
    最近更新 更多