雪花中的 LISTAGG Func 性能

时间:2021-05-23 12:52:44

标签: snowflake-cloud-data-platform

在 Snowflake 下运行 SQL,

select I_CLASS_ID,LISTAGG(I_CLASS,',') OVER(PARTITION BY I_CLASS_ID) 
FROM "SNOWFLAKE_SAMPLE_DATA"."TPCDS_SF100TCL"."ITEM" 
WHERE I_CLASS_ID IS NOT NULL

使用 XSmall Warehouse 运行 SQL。

查询耗时超过 40 分钟,但仍在运行,不得不中止。这个表相当小,所以试图理解为什么它需要这么长时间。该配置文件指出,4 个节点中有 1 个在完成大部分工作。有什么理由吗?

select LISTAGG(I_CLASS,',') OVER(PARTITION BY I_CLASS_ID) 
FROM "SNOWFLAKE_SAMPLE_DATA"."TPCDS_SF100TCL"."ITEM" 
WHERE I_CLASS_ID IS NOT NULL

上一个是瞬间运行。

2 个答案:

答案 0 :(得分:0)

第一个,对每一行进行聚合,所以如果你有 100 万行,你将得到 100 万行,以及所有的 id。

第二个while应该给出相同的结果,优化器可能会告诉它可以运行SQL:

SELECT A.I_CLASS_ID
    B.LIST
FROM FROM "SNOWFLAKE_SAMPLE_DATA"."TPCDS_SF100TCL"."ITEM" AS A
JOIN (
    SELECT I_CLASS_ID, 
        LISTAGG(I_CLASS,',') AS list
    FROM "SNOWFLAKE_SAMPLE_DATA"."TPCDS_SF100TCL"."ITEM" 
    WHERE I_CLASS_ID IS NOT NULL
    GROUP BY 1
) AS B
    ON A.I_CLASS_ID = B.I_CLASS_ID;

这将返回 100 万行,但速度会非常快。

我怀疑你真正想要的只是内部部分。

答案 1 :(得分:0)

您没有说明 #2 的查询计划是什么,但我怀疑它是在“瞬间”运行的。 它尝试了您的两个查询并在 2 分钟以上后将其杀死。 然后我跑了: 选择 I_CLASS_ID,LISTAGG(I_CLASS,',') OVER(PARTITION BY I_CLASS_ID) 来自 "SNOWFLAKE_SAMPLE_DATA"."TPCDS_SF100TCL"."ITEM" WHERE I_CLASS_ID 为空; 不到 1 秒。

然后我跑了:

select i_class_id,avg(length(i_class)),max(length(i_class)) from item group by 1;

关注:

select i_class_id,count(i_class)*8 from item where i_class_id is not null group by 1;

您正在创建非常大的列表,大小从 125 KB 到 625 KB。 建议您尝试更大的 DW 大小。此外,请确保您长时间运行的查询不是由于排队。