我使用一个表来更新另一个表。这两个表都有聚集索引,其中前 4 列是相同类型的数据。
CREATE UNIQUE CLUSTERED INDEX [i109139_I_109139CLI_44C9176D64C84ECB959C0EAA6AE7A4F4] ON [dbo].[t109139_44C9176D64C84ECB959C0EAA6AE7A4F4]
(
[PARTITION] ASC,
[DATAAREAID] ASC,
[ITEMID] ASC,
[INVENTSERIALID] ASC,
[RECID] ASC
)
GO
ALTER TABLE [dbo].[INVENTSERIAL] ADD CONSTRAINT [I_1204ITEMSERIALIDX] PRIMARY KEY CLUSTERED
(
[PARTITION] ASC,
[DATAAREAID] ASC,
[ITEMID] ASC,
[INVENTSERIALID] ASC
)
以下是我用来更新表的查询
UPDATE T1
SET NOTFORPROJECTS = T2.LANNOTFORPROJECTS
FROM tempdb."DBO".t109139_44C9176D64C84ECB959C0EAA6AE7A4F4 T1
CROSS JOIN LANINVENTSERIALVIEW T2
WHERE T1.PARTITION = 5637144576
AND T1.DATAAREAID = N'lan'
AND T2.PARTITION = 5637144576
AND T2.DATAAREAID = N'lan'
AND T2.INVENTSERIALID = T1.INVENTSERIALID
AND T2.ITEMID = T1.ITEMID
AND T2.DATAAREAID = T1.DATAAREAID
AND T2.PARTITION = T1.PARTITION
当我查看查询计划时,我注意到它确实使用了两个表的聚集索引,但它执行哈希匹配而不是合并联接。我发现这是出乎意料的,因为所使用的数据都应该按相等运算符进行排序。
因此,然后我尝试强制合并联接,似乎 SQL Server 仍然使用这两个聚集索引,但首先将两个表中的数据从 ItemId,InventSerialId 排序为 InventSerialId,ItemId,然后使用它来执行合并联接。所以它基本上交换了两列。
请注意,在 InventSerial 表中,只有 1 个 InventSerialId 是空字符串,而在我更新的另一个表中,将会有许多空字符串(非空)InventSerialId。我不知道这是否相关。
查询计划:
我也可以重现这个(小提琴)。
如果你改变
到
它能够生成所需的计划(Fiddle 中的最终查询中没有排序运算符)。
有点不满意的是,您必须这样做,但之前使用
MERGE
join 和MERGE
union 我还发现需要进行调整才能获得希望的计划(示例)。Paul White 之前评论过上面的例子
您发布查询的方式与计划中可用的查询有很大不同。这是括号。通过将这些放在连接标准周围,您可以在优化器上强制执行优先处理的逻辑顺序。因此,优化器看不到使用有序数据的方法。这意味着散列连接,或者当您强制合并连接时,排序操作。
这是来自计划: