Snowflake中嵌套查询的全表扫描

问题描述 投票:0回答:1

在解决任务和查看 Snowflake 文档的特定时间之后,我注意到查询的可读性和可能的性能改进的潜在改进。我的查询使用嵌套相关查询来检查主表是否有任何现有更新,使用单独的表进行更改。两个表都没有明确的 PK 或对允许值的任何其他约束。 这是一个简化查询的示例:

SELECT a.*
  FROM tableA a
 WHERE EXISTS (
               SELECT 1
                 FROM tableA_CDC a_cdc
                WHERE a.column1 = a_cdc.column1
                  AND a.column2 = a_cdc.column2
                  AND (a.column3 = a_cdc.column3 OR (a.column3 IS NULL AND a_cdc.column3 IS NULL))
              )

我对最后一个谓词感兴趣(a.column3 = a_cdc.column3 OR(a.column3 IS NULL AND a_cdc.column3 IS NULL))。对于column3值可以为空,所以我们想从主表中获取行。 Column1和column2不能有空值,我们可以忽略空处理。

我发现的问题不仅在于可读性,而且正如我注意到的那样在于性能。基本上,如果我们仅通过“=”进行比较或检查两列是否均为 NULL,则一切正常(使用查询配置文件)。每个谓词的数据计数总和给出了正确的结果。但是,如果我们对 equals 或 is null 进行分组条件,那么我们就有正确的更改计数,但查询配置文件显示已执行全表扫描。

在文档中,我发现了名为“EQUAL_NULL”的函数,该函数允许空安全地比较两个表达式。如果我通过用 EQUAL_NULL 替换最后一个分组谓词来修改查询,那么结果是正确的并且没有全表扫描。

SELECT a.*
  FROM tableA a
 WHERE EXISTS (
               SELECT 1
                 FROM tableA_CDC a_cdc
                WHERE a.column1 = a_cdc.column1
                  AND a.column2 = a_cdc.column2
                  AND EQUAL_NULL(a.column3, a_cdc.column3)
              )

有什么想法为什么我们在第一种情况下进行全表扫描吗?

sql snowflake-cloud-data-platform sql-execution-plan full-table-scan
1个回答
0
投票

我也遇到这个问题了。如果没有查询配置文件中的一些信息,就很难确切地知道查询发生了什么。然而,当我遇到这个问题时,WHERE 子句中的 OR 几乎就像笛卡尔连接一样。因为我正在相互比较两个不同表中的列(类似于联接),所以查询似乎是将一个表中的值与另一个表中的所有值进行比较(类似于像 the这篇文章中有一个)。我通过将表格合并在一起解决了这个问题:

SELECT 1
FROM tableA_CDC a_cdc
WHERE a.column1 = a_cdc.column1
              AND a.column2 = a_cdc.column2
              AND a.column3 = a_cdc.column3

UNION ALL

SELECT 1
FROM tableA_CDC a_cdc
WHERE a.column1 = a_cdc.column1
              AND a.column2 = a_cdc.column2
              AND a.column3 IS NULL AND a_cdc.column3 IS NULL

这极大地改善了我自己的查询,并且它反映了我上面共享的链接(以及许多其他链接)中的答案。

另外,只要想到这个表的功能,当我想到检查表更新时,我总是会想到streams。不确定您对它们有多熟悉,但根据您要使用这些更新执行的操作,我强烈推荐流和任务。

© www.soinside.com 2019 - 2024. All rights reserved.