首页 > 解决方案 > 为什么 CTE 在 Sql 数据仓库中的性能比临时表好得多?

问题描述

我想从一个大表(大约 10 亿行)中选择与 id 匹配的数据,该表与从 json 传入数据创建的表相匹配。

这是我首先做的:

SELECT * 
#JsonIds 
FROM OPENJSON(CONVERT(VARCHAR(MAX), '[{"id": "18897126"},{"id": "710990568"},{"id": "610990568"},{"id": "510990568"}]')) 
WITH (id BIGINT); 

SELECT * 
FROM #jsonIds j 
INNER JOIN [schema].[myBigTable] t ON t.id = j.id

这表现得很糟糕。花了将近3分钟才完成!

经过几次尝试,我决定看看 CTE 的表现如何:

WITH JsonIds AS 
( 
    SELECT *     
    FROM OPENJSON(CONVERT(VARCHAR(MAX), '[{"id": "18897126"},{"id": "710990568"},{"id": "610990568"},{"id": "510990568"}]')) 
    WITH (id BIGINT) 
)  
SELECT p.* 
FROM [schema].[myBigTable] p 
inner join JsonIds j on p.id = j.id

令我惊讶的是,CTE 变得更好。花了不到一秒钟的时间。

为什么 CTE 在这样一个简单的查询上表现得这么好?

标签: azure-sql-data-warehouse

解决方案


尝试向临时表添加统计信息:

SELECT * 
INTO #JsonIds 
FROM OPENJSON(CONVERT(VARCHAR(MAX), '[{"id": "18897126"},{"id": "710990568"},{"id": "610990568"},{"id": "510990568"}]')) 
WITH (id BIGINT); 

CREATE STATISTICS StatId on #JsonIds (id);

SELECT * 
FROM #jsonIds j 
INNER JOIN [schema].[myBigTable] t ON t.id = j.id

临时表上不会发生自动创建统计信息。所以 Azure DW 可能对临时表的内容做出了错误的假设。

如果上述方法没有帮助,请尝试将单词放在EXPLAIN每个语句之前,并在问题中包含生成的 XML 解释计划,以便我们可以看到它在做什么。


推荐阅读