11

我刚刚发现了该TABLESAMPLE子句,但令人惊讶的是它没有返回我指定的行数。

我使用的表有约 1400 万行,我想要一个 10000 行的任意样本。

select * from tabData TABLESAMPLE(10000 ROWS)

每次执行时,我得到的不是 10000,而是不同的数字(在 8000 到 14000 之间)。

这是怎么回事,我是否误解了 的预期目的TABLESAMPLE

编辑

大卫的链接很好地解释了它。

这以一种有效的方式总是返回 10000 个大致随机的行:

select TOP 10000 * from tabData TABLESAMPLE(20000 ROWS);

并且该REPEATABLE选项有助于始终保持不变(除非数据已更改)

select TOP 10000 * from tabData TABLESAMPLE(10000 ROWS) REPEATABLE(100);

因为我想知道使用TABLESAMPLE大量行来确保(?)我得到正确的行号是否更昂贵,所以我测量了它;

1.循环(20次):

select TOP 10000 * from tabData TABLESAMPLE(10000 ROWS);

(9938 row(s) affected)
(10000 row(s) affected)
(9383 row(s) affected)
(9526 row(s) affected)
(10000 row(s) affected)
(9545 row(s) affected)
(9560 row(s) affected)
(9673 row(s) affected)
(9608 row(s) affected)
(9476 row(s) affected)
(9766 row(s) affected)
(10000 row(s) affected)
(9500 row(s) affected)
(9941 row(s) affected)
(9769 row(s) affected)
(9547 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(9478 row(s) affected)
First batch(only 10000 rows) completed in: 14 seconds!

2.循环(20次):

select TOP 10000 * from tabData TABLESAMPLE(10000000 ROWS);

(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
Second batch(max rows) completed in: 13 seconds!

3.loop:使用 ORDER BY NEWID() 对 100% 随机行进行反检查:

select TOP 10000 * from tabData ORDER BY NEWID();

(10000 row(s) affected)

在持续23 分钟的一次执行后取消

结论

令人惊讶的是,具有精确TOP子句和大量 inTABLESAMPLE的方法并不慢。因此,ORDER BY NEWID()如果行不是每行随机而是每页级别无关紧要(表的每个 8K 页被赋予一个随机值),这是一个非常有效的替代方案。

4

4 回答 4

5

请参阅此处的文章。您需要添加一个 top 子句和/或使用可重复选项来获取您想要的行数。

于 2012-05-23T18:39:42.633 回答
3

从文档。

返回的实际行数可能会有很大差异。如果您指定一个较小的数字,例如 5,您可能不会在样本中收到结果。

http://msdn.microsoft.com/en-us/library/ms189108(v=sql.90).aspx

于 2012-05-23T18:59:23.717 回答
1

此行为之前已记录在案。这里有一篇很好的文章。

我相信您可以通过每次使用相同的种子传递 REPEATABLE 来修复它。以下是文章的摘录:

...您会注意到每次都返回不同数量的行。在没有任何数据更改的情况下,重新运行相同的查询会不断给出不同的结果。这是 TABLESAMEPLE 子句的非确定性因素。如果表是静态的并且行未更改,则可能是在每次执行中返回不同数量的行的原因。系数为 10 PERCENT 不是表行或表记录的百分比,而是表数据页的百分比。一旦选定数据的样本页,则返回选定页中的所有行,它不会限制从该页中采样的行数。所有页面的填充因子取决于表的数据。这使得脚本每次执行时都会在结果集中返回不同的行数。REPEATABLE 选项使选定的样本再次返回。当 REPEATABLE 使用相同的 repeat_seed 值指定时,只要没有对表进行任何更改,SQL Server 就会返回相同的行子集。当 REPEATABLE 使用不同的 repeat_seed 值指定时,SQL Server 通常会返回表中行的不同样本。.

于 2012-05-23T18:39:33.683 回答
1

我观察到了同样的情况。

页面解释绝对有意义并敲响了警钟 - 当您的行大小固定时,您应该看到更多可预测的行数。在没有可为空或可变长度列的表上尝试它。

事实上,我只是用它来证明一个关于用它来更新的理论(你可能被我提出的同一个问题所激发),而选择 TABLESAMPLE (50000 ROWS) 实际上影响了 49,849 行。

于 2012-05-23T18:54:14.297 回答