gpt4 book ai didi

SQL - 加入存档表时避免完全扫描

转载 作者:行者123 更新时间:2023-12-05 01:24:12 26 4
gpt4 key购买 nike

由于在一些较大的表上运行完整扫描以获取报告,我遇到了一些性能问题。我已将范围缩小到查询的这一部分,但无法弄清楚如何在不更改结果的情况下避免扫描。

解释一下,我们有一个数据归档系统,每天将数据从事件表复制到归档表。在一段时间过去之前,数据不会从实时表中删除。这会导致事件表和存档表都具有相同的行,但行中的数据可能不匹配的状态。

这排除了 UNION 查询(​​这将消除完整扫描)。要求是报告显示实时数据,所以我也不能只查询存档表。

有什么想法吗?这是查询。两个表的主键都是 DetailIdent,但我在 OrderIdent 上有一个索引,因为它是返回父表的外键。你可以看到,如果主表结果存在,我们就取主表结果,否则我们回退到归档数据。

SELECT COALESCE(RegOD.OrderIdent, ArcOD.OrderIdent) AS OrderIdent,
COALESCE(RegOD.Quantity, ArcOD.Quantity) AS Quantity,
COALESCE(RegOD.LoadQuan, ArcOD.LoadQuan) AS LoadQuan,
COALESCE(RegOD.ShipQuan, ArcOD.ShipQuan) AS ShipQuan,
COALESCE(RegOD.RcvdQuan, ArcOD.RcvdQuan) AS RcvdQuan,
COALESCE(RegOD.UOM, ArcOD.UOM) AS UOM,
COALESCE(RegOD.SkidType, ArcOD.SkidType) AS SkidType,
COALESCE(RegOD.Product, ArcOD.Product) AS Product,
COALESCE(RegOD.PkgCode, ArcOD.PkgCode) AS PkgCode
FROM OrderDetail RegOD
FULL JOIN dbo.ArcOrderDtl ArcOD
ON ArcOD.DetailIdent = RegOD.DetailIdent
WHERE COALESCE(RegOD.OrderIdent, ArcOD.OrderIdent) = 717010

execution plan showing two clustered index full scans

最佳答案

过滤谓词 COALESCE(RegOD.OrderIdent,ArcOD.OrderIdent) = 717010 会降低性能,它会强制引擎先执行完整扫描,然后再过滤数据。

选项 1 - 重新表述 COALESCE() 函数

改写 COALESCE() 函数,让引擎完成它的工作。运气好的话,引擎会足够聪明,可以找到优化。在这种情况下,查询可以采用以下形式:

SELECT
COALESCE(RegOD.OrderIdent,ArcOD.OrderIdent) AS OrderIdent,
COALESCE(RegOD.Quantity,ArcOD.Quantity) AS Quantity,
COALESCE(RegOD.LoadQuan,ArcOD.LoadQuan) AS LoadQuan,
COALESCE(RegOD.ShipQuan,ArcOD.ShipQuan) AS ShipQuan,
COALESCE(RegOD.RcvdQuan,ArcOD.RcvdQuan) AS RcvdQuan,
COALESCE(RegOD.UOM,ArcOD.UOM) AS UOM,
COALESCE(RegOD.SkidType,ArcOD.SkidType) AS SkidType,
COALESCE(RegOD.Product,ArcOD.Product) AS Product,
COALESCE(RegOD.PkgCode,ArcOD.PkgCode) AS PkgCode
FROM OrderDetail RegOD
FULL JOIN dbo.ArcOrderDtl ArcOD ON ArcOD.DetailIdent = RegOD.DetailIdent
WHERE RegOD.OrderIdent = 717010 or ArcOD.OrderIdent = 717010

选项 2 - 将左连接与右反连接相结合,而不是使用完整连接

如果引擎没有优化上面的选项 #1,您仍然可以尝试将左连接与右反连接结合起来,而不是编写完整连接(它们是等效的)。它肯定更冗长,但在这种情况下,它清楚地显示了引擎要做什么。此查询可能如下所示:

SELECT -- left join here
COALESCE(RegOD.OrderIdent,ArcOD.OrderIdent) AS OrderIdent,
COALESCE(RegOD.Quantity,ArcOD.Quantity) AS Quantity,
COALESCE(RegOD.LoadQuan,ArcOD.LoadQuan) AS LoadQuan,
COALESCE(RegOD.ShipQuan,ArcOD.ShipQuan) AS ShipQuan,
COALESCE(RegOD.RcvdQuan,ArcOD.RcvdQuan) AS RcvdQuan,
COALESCE(RegOD.UOM,ArcOD.UOM) AS UOM,
COALESCE(RegOD.SkidType,ArcOD.SkidType) AS SkidType,
COALESCE(RegOD.Product,ArcOD.Product) AS Product,
COALESCE(RegOD.PkgCode,ArcOD.PkgCode) AS PkgCode
FROM OrderDetail RegOD
LEFT JOIN dbo.ArcOrderDtl ArcOD ON ArcOD.DetailIdent = RegOD.DetailIdent
WHERE RegOD.OrderIdent = 717010
UNION ALL
SELECT -- right anti-join here
OrderIdent,
Quantity,
LoadQuan,
ShipQuan,
RcvdQuan,
UOM,
SkidType,
Product,
PkgCode
FROM dbo.ArcOrderDtl ArcOD
LEFT JOIN OrderDetail RegOD ON ArcOD.DetailIdent = RegOD.DetailIdent
WHERE ArcOD.OrderIdent = 717010 and RegOD.DetailIdent IS NULL

关于SQL - 加入存档表时避免完全扫描,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71564218/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com