我在 SQL Server Azure 托管实例上有以下代码,性能非常糟糕。
INSERT INTO #CU WITH (TABLOCKX) (LA_ID, CU_ID)
SELECT la.LA_ID,
c2.CU_ID
FROM #la la
INNER JOIN dbo.T1 c ON c.CU_ID = la.CU_ID
INNER JOIN dbo.T1 c2 ON c2.Parent_CU_ID = c.Parent_CU_ID
WHERE c.Parent_CU_ID > 0
AND c.CU_ID <> c2.CU_ID
AND la.Flag1 = 1
AND EXISTS (SELECT 1 FROM #cid WHERE c2.CU_ID = ID)
我在 T1.Flag 上有一个筛选索引,如果我删除不等式,性能就超出了可接受的范围(5 分钟缩短到 10 秒),因此我相信我的问题在于不等式,但我想不出任何模式可以给我相同的结果,但性能更好。有什么建议吗?计划
#TeamLegacyCE
由于问题不在于表级基数,因此您可能需要强制使用旧式基数估算器。兼容性级别 150 使用不同的连接估算,这看起来非常不正确。
你可以通过这个提示来做到这一点:
当然还有其他问题,可以通过更好的连接估计来纠正。
低计划成本:16k 行估计值导致估计成本约为 3.4 查询费用,这可让您获得串行计划。当您的实际行数为 144,688,210 行和 61,962,838 行时,这是一条糟糕的选择。
无批处理模式:在连接那么多行时,行存储上的批处理模式与并行计划一起会是一个更可接受的选择。同样,它可能会在正确估计和计算成本的计划下自然启动,但如果没有,您将需要使用通常的技巧让优化器选择它。
除此之外
我可能需要再检查一下这个查询是否写得正确。从几万行开始,然后产生 1.44 亿行和 6200 万行的连接结果,这看起来相当俗气。
此外,即使纠正上述项目也只能将查询执行时间减少到大约 4 分钟(但如果插入最终按照提示进入并行区域,则可能更短
TABLOCK
)。这很可能无法修复,因为你使用的是微软云产品,磁盘由热沥青制成。在那里插入 6200 万行仍会是一个症结所在,这就是我询问查询是否正确编写的原因。
如果写得正确,您可能会发现通过添加
DISTINCT
或ROW_NUMBER
组合会有所缓解。插入的许多行可能是不必要的重复项,可以从最终结果中删除。