用于提高查询性能的 Top-K 修剪¶
如果一个 SELECT 语句包含 LIMIT 和 ORDER BY 子句,Snowflake 通常会扫描所有符合条件的行,因为任何行都可能是 Top-K 结果的一部分,其中 K 是 LIMIT 子句的值。使用 Top-K 修剪,当 Snowflake 确定由 K 条记录组成的结果集中没有剩余记录时,就会停止扫描。
Top-K 修剪可以提高包含 LIMIT 和 ORDER BY 子句的 SELECT 语句的性能。大表上的查询从 Top-K 修剪中受益最大。
使用 Top-K 修剪的查询¶
仅当以下所有情况都为真时,Snowflake 才会应用 Top-K 修剪:
查询同时包含 ORDER BY 子句和 LIMIT 子句。
ORDER BY 子句中指定的第一列具有以下数据类型之一:
可表示为整数的数据类型(即,INTEGER 类型、DATE 类型 或 TIMESTAMP 类型)。不支持返回整数的表达式,如强制类型转换。
字符串或二进制数据类型,包括 已排序字符串。
VARIANT 列中具有支持的基础类型(即,前面两个项目符号列表项中列出的类型)并转换为该基础类型的字段。
如果指定了多列,Snowflake 仅考虑第一列。
当查询包含联接时,ORDER BY 列为较大表中的一列。在数据仓库中,较大的表通常被称为 事实表 (link removed) 或探测端。较小的表则称为 维度表 (link removed) 。
具有 LIMIT 子句且速度已经很快的查询(例如全表扫描速度很快的查询)可能无法受益于 Top-K 修剪。返回少于 K 行的查询也不会受益。
包含 ORDER BY ...的查询仅当可空字段上的 DESCENDING 还指定 NULLS LAST 时,才会对其进行修剪。
VARIANT 列查询¶
本节提供 VARIANT 列中字段的查询示例,以显示可以使用 Top-K 修剪的查询类型。
创建具有 VARIANT 列的表并插入数据:
CREATE OR REPLACE TABLE variant_topk_test (var_col VARIANT);
INSERT INTO variant_topk_test
SELECT PARSE_JSON(column1)
FROM VALUES
('{"s": "aa", "i": 1}'),
('{"s": "bb", "i": 2}'),
('{"s": "cc", "i": 3}'),
('{"s": "dd", "i": 4}'),
('{"s": "ee", "i": 5}'),
('{"s": "ff", "i": 6}'),
('{"s": "gg", "i": 7}'),
('{"s": "hh", "i": 8}'),
('{"s": "ii", "i": 9}'),
('{"s": "jj", "i": 10}');
此表相对较小,以提供一个示例,但请记住 Top-K 修剪有利于较大的表。
此表上的以下查询可以使用 Top-K 修剪:
SELECT * FROM variant_topk_test ORDER BY TO_VARCHAR(var_col:s) LIMIT 5;
SELECT * FROM variant_topk_test ORDER BY var_col:s::VARCHAR LIMIT 5;
SELECT * FROM variant_topk_test ORDER BY TO_NUMBER(var_col:i) LIMIT 5;
SELECT * FROM variant_topk_test ORDER BY var_col:i::NUMBER LIMIT 5;
以下查询不能使用 Top-K 修剪,因为该值未强制转换为基础数据类型:
SELECT * FROM variant_topk_test ORDER BY var_col:s LIMIT 5;
以下查询不能使用 Top-K 修剪,因为该值被强制转换为与基础数据类型不同的数据类型:
SELECT * FROM variant_topk_test ORDER BY var_col:i::VARCHAR LIMIT 5;
包含聚合函数的查询¶
仅当包含 聚合函数 的查询满足以下所有条件时,才会对其进行修剪:
其中包括一个 GROUP BY 子句。
第一个 ORDER BY 列也是 GROUP BY 列。
第一个 ORDER BY 列不是聚合列。
例如,以下查询可以使用 Top-K 修剪,因为第一个 ORDER BY 列 c2
也是 GROUP BY 列,而非聚合列:
SELECT c1, c2, c3, COUNT(*) AS agg_col
FROM mytable
GROUP BY c1, c2, c3
ORDER BY c2, c1, agg_col, c3
LIMIT 5;
以下查询不能使用 Top-K 修剪,因为第一个 ORDER BY 列 agg_col
是聚合列:
SELECT c1, c2, c3, COUNT(*) AS agg_col
FROM mytable
GROUP BY c1, c2, c3
ORDER BY agg_col, c2, c1
LIMIT 5;