- 类别:
SAMPLE / TABLESAMPLE¶
返回从指定表中随机采样的行的子集。您可以指定不同类型的采样方法,也可以对表的一部分或固定数量的行进行采样:
当您按照指定概率对数据表进行采样时,返回的行数取决于数据表的大小和设定的采样概率。您可以指定种子以使采样具有确定性。
当您指定固定行数进行采样时,查询将返回确切的指定行数,除非数据表的行数不足。
SAMPLE 与 TABLESAMPLE 同义,可以交换使用。
语法¶
SELECT ...
FROM ...
{ SAMPLE | TABLESAMPLE } [ samplingMethod ]
[ ... ]
其中:
samplingMethod ::= { { BERNOULLI | ROW } ( { <probability> | <num> ROWS } ) | { SYSTEM | BLOCK } ( <probability> ) [ { REPEATABLE | SEED } ( <seed> ) ] }
参数¶
{ BERNOULLI | ROW }
或 .{ SYSTEM | BLOCK }
指定要使用的采样方法:
BERNOULLI`(或 :code:`ROW
):包含probability
为p/100
的每行。此方法类似于 为每行 掷一个加权的硬币。SYSTEM`(或 :code:`BLOCK
):包含probability
为p/100
的每个行块。此方法类似于 为每个行块 掷一个加权的硬币。此方法不支持固定大小的采样。
采样方法为可选。如果未指定方法,则默认为
BERNOULLI
。probability
或 .num ROWS
指定是根据表的一小部分还是根据表中的固定行数进行采样,其中:
probability
指定用于选择样本的百分比概率。可以是介于0
(未选择行)和100
(所有选择的行)之间的任何十进制数(包括这两个数字)。num
指定要从表中采样的行数(最多 100 万行)。可以是介于0
(未选择行)和1000000
之间的任意整数(包括这两个数字)。
除使用字面量来指定
probability
或num ROWS
之外,还可以使用会话变量或绑定变量。{ REPEATABLE | SEED ( seed ) }
指定种子值以使采样具有确定性。可以是介于
0
和2147483647
之间的任意整数(包括这两个数字)。该参数仅适用于SYSTEM
和BLOCK
采样。除使用字面量来指定
seed
之外,还可以使用会话变量或绑定变量。
使用说明¶
以下关键字可以交换使用:
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 (seed)
。例如,以下查询会产生错误:SELECT * FROM example_table SAMPLE SYSTEM (10 ROWS); SELECT * FROM example_table SAMPLE ROW (10 ROWS) SEED (99);
不支持对视图或子查询执行带
SEED (seed)
的采样。例如,以下查询会产生错误:SELECT * FROM (SELECT * FROM example_table) SAMPLE (1) SEED (99);
允许对联接的结果进行采样,但前提是满足以下 所有 条件:
样本基于行 (Bernoulli)。
采样不使用种子。
采样是在完全处理联接后完成的。因此,采样不会减少联接的行数,也不会降低联接的成本。示例 部分包含对联接结果进行采样的示例。
LIMIT 子句和 SAMPLE 子句都会返回表中行的子集。使用 LIMIT 子句时,Snowflake 会以尽可能最快的方式返回指定行数。使用 SAMPLE 子句时,Snowflake 会根据子句中指定的采样方法返回行。
性能注意事项¶
SYSTEM | BLOCK
采样通常比BERNOULLI | ROW
采样快。不带
seed
的采样通常比带seed
的采样快。固定大小的采样可能比基于小部分的等效采样慢,因为固定大小的采样会阻止某些查询优化。
示例¶
以下示例使用 SAMPLE 子句。
基于小部分的行采样¶
返回表的样本,其中每行都有 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);
联接采样¶
此示例演示如何对联接中的多个表进行采样。它对 table1
中 25% 的行和 table2
中 50% 的行进行了采样:
SELECT i, j
FROM
table1 AS t1 SAMPLE (25)
INNER JOIN
table2 AS t2 SAMPLE (50)
WHERE t2.j = t1.i;
SAMPLE
子句仅适用于一个表,而不适用于 SAMPLE
子句之前的所有表或整个表达式。下面的 JOIN
操作将 table1
中的所有行与``table2`` 中 50% 行的样本联接起来。它不会对联接两个表中所有行后产生的 50% 的行记录进行采样:
SELECT i, j
FROM table1 AS t1 INNER JOIN table2 AS t2 SAMPLE (50)
WHERE t2.j = t1.i;
要将 SAMPLE
子句应用于联接的结果而非联接中的各个表,请将联接应用于包含联接结果的内联视图。例如,将联接作为子查询执行,然后将 SAMPLE 应用于子查询的结果。下面的示例对大约 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);