当没有指定order by时,SELECT TOP如何工作?

Raz*_*t4x 18 sql t-sql sql-server select sql-order-by

MSDN文档说,当我们写

SELECT TOP(N) ..... ORDER BY [COLUMN]
Run Code Online (Sandbox Code Playgroud)

我们得到排序的前(n)行column(ascdesc取决于我们选择的内容)

但是如果我们没有指定任何顺序,msdn random就像这里Gail Erickson指出的那样说.正如他所指出的它应该是而不是.但正如那点那样unspecifiedrandom Thomas Lee

当TOP与ORDER BY子句一起使用时,结果集仅限于前N个有序行; 否则,它返回前N个行ramdom

所以,我在没有任何索引的表上运行此查询,首先我运行了这个..

SELECT *
FROM
    sys.objects so
WHERE
    so.object_id NOT IN (SELECT si.object_id
                         FROM
                             sys.index_columns si)
    AND so.type_desc = N'USER_TABLE'
Run Code Online (Sandbox Code Playgroud)

然后在其中一个表中,(实际上我在上面查询返回的所有表中尝试了下面的查询)并且我总是得到相同的行.

SELECT TOP (2) *
FROM
    MstConfigSettings
Run Code Online (Sandbox Code Playgroud)

这总是返回相同的2行,对于查询1返回的所有其他表也是如此.现在执行计划显示3个步骤..

在此输入图像描述

正如您所看到的,没有索引查找,它只是一个纯表扫描,并且

在此输入图像描述

Top行示出了实际不为2,也是如此的Table Scan; 事实并非如此(我有很多行).

但是,当我运行类似的东西

SELECT TOP (2) *
FROM
    MstConfigSettings
ORDER BY
    DefaultItemId
Run Code Online (Sandbox Code Playgroud)

执行计划显示

在此输入图像描述

在此输入图像描述

所以,当我不申请时ORDER BY,步骤是不同的(没有排序).但问题是,如果TOP没有Sort,为什么以及如何始终给出相同的结果,这是如何工作的?

Mar*_*ith 20

无法保证您获得哪两行.它只是从表扫描中检索到的前两个.

TOP一旦返回两个,执行计划中的迭代器将停止请求行.

可能对于堆的扫描,这将是分配顺序中的前两行,但这不能保证.例如,SQL Server可能使用高级扫描功能,这意味着您的扫描将读取最近从另一个并发扫描中读取的页面.

  • @ Razort4x - 我认为你的困惑是因为在链接页面中使用了单词random.那是不对的.SQL Server不会故意随机化结果,它只是对你得到的两个没有任何特别的承诺.如果你真的想要两个随机行,你需要`ORDER BY NEWID()`.这就是为什么修改文档以说"未定义"不是随机的. (10认同)
  • 因为表扫描始终以相同的方式运行.不保证并不意味着您不可能获得相同的结果.它只是意味着您不能依赖任何特定的观察顺序,并且如果它发生变化则会抱怨.我所知道的唯一情况是,如果先进的扫描被踢入,你将无法获得第一个分配页面中的前两行. (6认同)