- 类别:
SAMPLE / TABLESAMPLE¶
返回从指定表中随机采样的行的子集。支持以下采样方法:
对表的一小部分进行采样,并指定包含给定行的概率。返回的行数取决于表的大小和请求的概率。可以指定种子以使采样具有确定性。
对固定的指定行数进行采样。除非表包含较少的行,否则将返回确切数量的指定行。
SAMPLE 与 TABLESAMPLE 同义,可以交换使用。
语法¶
SELECT ...
FROM ...
{ SAMPLE | TABLESAMPLE } [ samplingMethod ] ( { <probability> | <num> ROWS } ) [ { REPEATABLE | SEED } ( <seed> ) ]
[ ... ]
其中:
samplingMethod ::= { { BERNOULLI | ROW } | { SYSTEM | BLOCK } }
BERNOULLI | ROW
或 .SYSTEM | BLOCK
指定要使用的采样方法:
BERNOULLI`(或 :samp:`ROW
):包含probability
为p/100
的每行。类似于为每行掷一个加权的硬币。SYSTEM`(或 :samp:`BLOCK
):包含probability
为p/100
的每个行块。类似于为每个行块掷一个加权的硬币。此方法不支持固定大小的采样。
采样方法是可选的。如果未指定方法,则默认为
BERNOULLI
。probability
或 .num ROWS
指定是根据表的一小部分还是根据表中的固定行数进行采样,其中:
probability
指定用于选择样本的百分比概率。可以是介于0
(未选择行)和100
(所有选择的行)之间的任何十进制数(包括这两个数字)。num
指定要从表中采样的行数(最多 100 万行)。可以是介于0
(未选择行)和1000000
之间的任意整数(包括这两个数字)。
REPEATABLE | SEED ( seed )
指定种子值以使采样具有确定性。可以是介于
0
和2147483647
之间的任意整数(包括这两个数字)。
使用说明¶
以下关键字可以交换使用:
SAMPLE | TABLESAMPLE
BERNOULLI | ROW
SYSTEM | BLOCK
REPEATABLE | SEED
返回的行数取决于指定的采样方法:
- 基于小部分:
对于
BERNOULLI | ROW
采样,预计返回的行数为(p/100)*n
。对于
SYSTEM | BLOCK
采样,样本可能会有偏差,特别是对于小表。
备注
对于非常大的表,这两种方法之间的差异应该可以忽略不计。
此外,由于采样是一个概率过程,因此返回的行数并不完全等于
(p/100)*n
行,但是会很接近。如果未指定
seed
, SAMPLE 会在重复同一查询时生成不同的结果。如果表未发生变更,并且指定了相同的
seed
和probability
,SAMPLE 会生成相同的结果。但是,对表副本进行采样可能不会返回与对原始表进行采样相同的结果,即使指定了相同的probability
和seed
也是如此。
- 固定大小:
如果表大于请求的行数,则始终返回请求的行数。
如果表小于请求的行数,则返回整个表。
固定大小的采样不支持
SYSTEM | BLOCK
和seed
。例如,以下查询会产生错误:select * from example_table sample system (10 rows); select * from example_table sample row (10 rows) seed (99);
不支持对视图或子查询进行带
seed
的采样。例如,以下查询会产生错误:select * from (select * from example_table) sample (1) seed (99);
允许对
JOIN
的结果进行采样,但前提是满足以下 所有 条件:样本基于行 (Bernoulli)。
采样不使用种子。
采样是在完全处理联接后完成的。因此,采样不会减少联接的行数,也不会降低
JOIN
的成本。示例 部分包含了对JOIN
的结果进行采样的示例。除了使用字面量来指定
probability | num ROWS
和seed
之外,还可以使用会话变量或绑定变量。
性能注意事项¶
SYSTEM | BLOCK
采样通常比BERNOULLI | ROW
采样快。不带
seed
的采样通常比带seed
的采样快。固定大小的采样可能比基于小部分的等效采样慢,因为固定大小的采样会阻止某些查询优化。
示例¶
基于小部分的行采样¶
返回表的样本,其中每行都有 10% 的概率包含在样本中:
SELECT * FROM testtable SAMPLE (10);
返回表的样本,其中每行都有 20.3% 的概率包含在样本中:
SELECT * FROM testtable TABLESAMPLE BERNOULLI (20.3);
返回整个表,包括表中的所有行:
SELECT * FROM testtable TABLESAMPLE (100);
返回一个空样本:
SELECT * FROM testtable SAMPLE ROW (0);
此示例演示如何对联接中的多个表进行采样:
SELECT i, j FROM table1 AS t1 SAMPLE (25) -- 25% of rows in table1 INNER JOIN table2 AS t2 SAMPLE (50) -- 50% of rows in table2 WHERE t2.j = t1.i ;
SAMPLE
子句仅适用于一个表,而不适用于 SAMPLE
子句之前的所有表或整个表达式。以下 JOIN
操作将 t1 的所有行联接到由 table2 中 50% 的行组成的样本;它不会对联接两个表中的所有行得到的 50% 的行进行采样:
SELECT i, j FROM table1 AS t1 INNER JOIN table2 AS t2 SAMPLE (50) WHERE t2.j = t1.i ;
要将 SAMPLE
子句应用于 JOIN
的结果而不是 JOIN
中的各个表,请将 JOIN
应用于包含 JOIN
的结果的内联视图。例如,将 JOIN
作为子查询执行,然后将 SAMPLE 应用于子查询的结果。下面的示例对 JOIN
返回的行的大约 1% 进行采样:
select * from ( select * from t1 join t2 on t1.a = t2.c ) sample (1);
基于小部分的块采样(带种子)¶
返回表的样本(其中每个行块都有 3% 的概率包含在样本中),并将种子设置为 82:
SELECT * FROM testtable SAMPLE SYSTEM (3) SEED (82);
返回表的样本(其中每个行块都有 0.012% 的概率包含在样本中),并将种子设置为 99992:
SELECT * FROM testtable SAMPLE BLOCK (0.012) REPEATABLE (99992);
备注
如果在不对表进行任何变更的情况下再次运行这两个查询中的任何一个,它们将返回相同的样本集。
固定大小的行采样¶
返回包含 10 行的固定大小的样本,每行都有 min(1, 10/n)
的概率包含在样本中,其中 n
是表中的行数:
SELECT * FROM testtable SAMPLE (10 ROWS);