用于提高查询性能的 Top-K 修剪

如果一个 SELECT 语句包含 LIMITORDER 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 子句中指定的第一列具有以下数据类型之一:

    如果指定了多列,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}');
Copy

此表相对较小,以提供一个示例,但请记住 Top-K 修剪有利于较大的表。

此表上的以下查询可以使用 Top-K 修剪:

SELECT * FROM variant_topk_test ORDER BY TO_VARCHAR(var_col:s) LIMIT 5;
Copy
SELECT * FROM variant_topk_test ORDER BY var_col:s::VARCHAR LIMIT 5;
Copy
SELECT * FROM variant_topk_test ORDER BY TO_NUMBER(var_col:i) LIMIT 5;
Copy
SELECT * FROM variant_topk_test ORDER BY var_col:i::NUMBER LIMIT 5;
Copy

以下查询不能使用 Top-K 修剪,因为该值未强制转换为基础数据类型:

SELECT * FROM variant_topk_test ORDER BY var_col:s LIMIT 5;
Copy

以下查询不能使用 Top-K 修剪,因为该值被强制转换为与基础数据类型不同的数据类型:

SELECT * FROM variant_topk_test ORDER BY var_col:i::VARCHAR LIMIT 5;
Copy

包含聚合函数的查询

仅当包含 聚合函数 的查询满足以下所有条件时,才会对其进行修剪:

  • 其中包括一个 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;
Copy

以下查询不能使用 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;
Copy
语言: 中文