2011-02-12 68 views
33

我知道,如果我运行此查询“order by newid()” - 它是如何工作的?

select top 100 * from mytable order by newid() 

它会从我的表中获取100个随机记录。

但是,我对它的工作原理有些困惑,因为我在select列表中看不到newid()。有人可以解释吗?这里有什么特别的关于newid()

+0

注意,这是一个缓慢的方式来获得100个随机项,除非数据库服务器识别这作为优化的已知模式。 – CodesInChaos 2011-02-12 18:37:23

+0

它也只是伪随机的。如果您需要真正的安全性随机性,请不要使用此方法。 – 2011-02-12 18:40:45

+2

您的ORDER BY`子句中的列不需要出现在SQL Server的SELECT语句中。 – Gabe 2011-02-12 18:51:57

回答

30
NEWID() 210

我知道NewID()做什么,我只是 试图了解它将如何帮助 在随机选择。是认为 (1)选择语句将选择从MYTABLE 一切,(2)选择的每个 列,由NEWID()生成的 唯一标识符粘性, (3)的行通过此 唯一标识符和(排序4)从排序列表中挑选 top 100?

是。这几乎完全正确(除非它不一定需要对全部行进行排序)。您可以通过查看实际的执行计划来验证这一点。

SELECT TOP 100 * 
FROM master..spt_values 
ORDER BY NEWID() 

的计算标量操作者增加了对(在我的示例查询2506的表)的每一行的列NEWID()然后在表中的行是由该列与选定的顶端100排序。

SQL服务器实际上并不需要那么它使用它试图在内存中执行整个排序操作的TOP N排序操作员从100位下降整套排序(for small values of N

Plan

4

MSDN说:

NEWID()创建类型 唯一标识符的唯一值。

并且您的表格将按此随机值排序。

10

一般来说它的工作原理是这样的:

  • MYTABLE所有行是“循环”
  • NEWID()为每个行
  • 行被根据从随机数排序执行
  • 100第一行被选择
6

的这里的关键是NEWID函数,它为每行在内存中生成一个全局唯一标识符(GUID)。根据定义,GUID是唯一且相当随机的;因此,当您使用ORDER BY子句对该GUID进行排序时,您会得到表中行的随机排序。以前10%(或任何你想要的百分比)将会给你一个表格中行的随机抽样。

提出了NEWID查询;它很简单,适用于小桌子。但是,当您将它用于大型表格时,NEWID查询有一个很大的缺点。 ORDER BY子句会将表中的所有行复制到tempdb数据库中,并在那里对它们进行排序。这会导致两个问题: 排序操作通常与其相关的成本很高。排序可以使用很多磁盘I/O并且可以运行很长时间。 在最坏的情况下,tempdb可能会用尽空间。在最好的情况下,tempdb可能会占用大量的磁盘空间,永远不会在没有手动收缩命令的情况下回收。 您需要的是随机选择不使用tempdb的行,并且在表变大时不会变得太慢。下面是关于如何做一个新的想法:

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

此查询背后的基本理念是,我们要生成表中的每一行0到99之间的随机数,然后选择所有这些随机数小于指定百分比值的行。在这个例子中,我们希望随机选择大约10%的行;因此,我们选择所有那些随机数行小于10

1

使用select top 100 randid = newid(), * from mytable order by randid 你会再澄清..