雪花查询性能调优

sel*_*lva 2 snowflake-schema snowflake-cloud-data-platform

我有一个包含多个 ctes 的雪花查询,并使用 Talend 作业插入表中。执行查询需要超过 90 分钟。它是多个级联的ctes,一个调用另一个,另一个调用另一个。

\n\n

我想提高查询的性能。大概有1000行代码,我无法将其粘贴到这里。当我检查配置文件时,它显示了所有窗口函数和聚合函数,这会减慢查询速度。

\n\n

例如,顶部较慢的是,

\n\n
ROW_NUMBER\xe2\x80\x8b(\xe2\x80\x8b\xe2\x80\x8b)\xe2\x80\x8b OVER \xe2\x80\x8b(\xe2\x80\x8bPARTITION BY LOWER\xe2\x80\x8b(\xe2\x80\x8bS\xe2\x80\x8b.\xe2\x80\x8bSUBSCRIPTIONID\xe2\x80\x8b)\xe2\x80\x8b \n                   ORDER BY S\xe2\x80\x8b.\xe2\x80\x8bISROWCURRENT DESC NULLS FIRST, \n                      TO_NUMBER\xe2\x80\x8b(\xe2\x80\x8bS\xe2\x80\x8b.\xe2\x80\x8bSTARTDATE\xe2\x80\x8b)\xe2\x80\x8b DESC NULLS FIRST, \n                      IFF\xe2\x80\x8b(\xe2\x80\x8bS\xe2\x80\x8b.\xe2\x80\x8bENDDATE IS NULL, '29991231', S\xe2\x80\x8b.\xe2\x80\x8bENDDATE\xe2\x80\x8b)\xe2\x80\x8b DESC NULLS FIRST\xe2\x80\x8b)\xe2\x80\x8b \n
Run Code Online (Sandbox Code Playgroud)\n\n

占用 7.3% 的时间。您能建议一种替代方法来提高查询性能吗?

\n

All*_*len 5

问题是 1000 行对于任何查询分析器来说都很难优化。对于您和继承该代码的未来团队成员来说,这也会使故障排除变得更加困难。

\n\n

我建议分解查询并进行这些优化:

\n\n
    \n
  1. 使用CREATE TEMPORARY TABLE AS而不是 CTE。在创建表时添加ORDER BY要连接或过滤的列。临时表对于优化器来说更容易构建和以后使用。这ORDER BY有助于 Snowflake 了解后续与其他表的连接要优化哪些内容。它们也更容易排除故障。
  2. \n
  3. 在您的示例中,看看是否可以将此数据保留为永久列,以便 Snowflake 可以跳过转换部分并对其进行更好的统计:TO_NUMBER\xe2\x80\x8b(\xe2\x80\x8bS\xe2\x80\x8b.\xe2\x80\x8bSTARTDATE\xe2\x80\x8b)\xe2\x80\x8b 和IFF\xe2\x80\x8b(\xe2\x80\x8bS\xe2\x80\x8b.\xe2\x80\x8bENDDATE IS NULL, \'29991231\', S\xe2\x80\x8b.\xe2\x80\x8bENDDATE\xe2\x80\x8b)\xe2\x80\x8b.
  4. \n
  5. 作为步骤 2 的替代方案,不要按 startDate 和 endDate 排序,而是查看是否可以添加IDENTITYSEQUENCE或填充INTEGER可用作排序键的列。您还可以按字面意思命名这个新列 sortKey。DATETIME对整数进行排序比在 a 上运行函数然后按它排序要快得多。
  6. \n
  7. 如果任何 CTE 可以更改为物化视图,它们将是预先构建的并且速度会显着加快。
  8. \n
  9. 最后,在插入临时表之前,将所有数据暂存在临时表中(按创建目标表的相同列排序)。这将使插入步骤本身更快,并且 Snowflake 将更轻松地处理对该表的并发更改。
  10. \n
\n\n

笔记:

\n\n
    \n
  1. 要创建临时表:\ncreate or replace temporary table table1 as select * from dual;之后,您引用 table1 而不是您的代码而不是 CTE。
  2. \n
  3. 物化视图记录在此处。它们是企业版功能。他们的语法是:create materialized view mymv as select col1, col2 from mytable;
  4. \n
\n