繁体   English   中英

合并多个表时的SQL Server执行计划

[英]SQL Server Execution plan when combining multiple tables

我有一个存储过程,发出与以下查询类似的查询(pseudo-tsql)。

多个ParentIds作为参数(csv)传递,解析并插入到表变量@i 对于每个传入的ParentId ,我们查找StorageTable并将其包含在@i 现在,根据StorageTable列的值,我们需要通过ParentId从适当的表( Table1Table2Table3 )中提取数据。 在多个表之间没有重复的机会-因此是UNION ALL

当我检查实际的执行计划时,我发现我的大部分成本/子树成本(一半以上)都花在了StorageTable上,而这些甚至没有作为输入提供。

例如,如果我包括一个StorageTable = 'Table1' ,那么在执行计划中Table2的索引扫描将以很高的成本显示。

如我所料, STATISTICS IO不会显示对Table2的任何读取,但是根据实际的执行计划,数据访问点看起来很昂贵。

在我看来,如果不存在特定的StorageTable,则使用@i进行内部@i将返回空结果集,并使任何其他工作“短路”,不是吗?

有什么解决方案?

DECLARE @i AS TABLE
(
    ParentId INT,
    StorageTable VARCHAR(10)
)

INSERT INTO @i...
INSERT INTO @i...
INSERT INTO @i...

SELECT Col1, Col2, Col3
FROM dbo.Table1 AS T1
INNER JOIN (SELECT * FROM @i WHERE StorageTable = 'Table1') AS I
    ON T1.ParentId = I.ParentId
<joins>
<where clause>

UNION ALL

SELECT Col1, Col2, Col3
FROM dbo.Table2 AS T2
INNER JOIN (SELECT * FROM @i WHERE StorageTable = 'Table2') AS I
    ON T2.ParentId = I.ParentId
<joins>
<where clause>

UNION ALL

SELECT Col1, Col2, Col3
FROM dbo.Table3 AS T3
INNER JOIN (SELECT * FROM @i WHERE StorageTable = 'Table3') AS I
    ON T3.ParentId = I.ParentId
<joins>
<where clause>

在这种情况下,您应该几乎忽略子树成本。

即使在实际计划中,它们也仅基于估计。

根据您所说的STATISTICS IO输出,例如访问Table2的操作员的实际执行次数为0

但是,该计划可能会估计执行次数= 1。

(选择一个运算符后,您可以在SSMS的属性窗口中查看估计和实际数字)

如果该计划的一些分支具有执行数的低估 ,你可以尝试使用#temp代替列统计都考虑到表。

通过添加一些辅助变量和OPTION (RECOMPILE)您可以得到更具代表性的子树成本,但是它们仍然仅与建模假设和估计一样准确。

例如

DECLARE @T TABLE(
  X            INT,
  StorageTable VARCHAR(50));

INSERT INTO @T
VALUES      (1, 'Table1')

DECLARE @Branch1Exists BIT = iif(EXISTS(SELECT * FROM @T WHERE StorageTable = 'Table1'), 1, 0)
DECLARE @Branch2Exists BIT = iif(EXISTS(SELECT * FROM @T WHERE StorageTable = 'Table2'), 1, 0)

SELECT X
FROM   @T
       JOIN master..spt_values V
         ON [@T].X = number
WHERE  @Branch1Exists = 1
UNION ALL
SELECT X
FROM   @T
       JOIN sys.objects
         ON [@T].X = object_id
WHERE  @Branch2Exists = 1
OPTION (recompile) 

在编译时删除未执行的计划分支,而不是显示估计的单个执行成本。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM