如何使用多列索引优化 MERGE

How to optimize MERGE using multiple column index

我是 MERGE 的新手,也是一个索引新手,所以请多多包涵...

我有一个存储过程,它构建一个 #changes temp table,更新一个 prod_tbl table 基于 #changes,然后插入之前和在值进入 auto_update_log table 之后,随着重复的行快速增长。为了防止这种情况,我想使用 MERGE 语句。速度和线程安全是最重要的,因为这个 table 将全天被操纵。

auto_update_log 上没有任何现有索引,也没有任何类型的键。我的想法是使用键列(来自 auto_update_log table)和所有前后列来创建多列索引,以帮助加快 MERGE 的速度。将有 6 个前后列加上一个与 auto_update_log.

的 PK 相关的关键列

示例日志 Table:

CREATE TABLE dbo.sample_auto_update_log (
    id INT NOT NULL, --Primary key from [prod_tbl]
    item_a_before VARCHAR(25) NULL, --[prod_tbl].[item_a]
    item_a_detail VARCHAR(25) NULL, --Value from elsewhere in the DB that applies
    item_a_after VARCHAR(25) NULL, --The new value SET for [prod_tbl].[item_a]
    update_count INT NOT NULL DEFAULT (0),
    update_datetime DATETIME NOT NULL DEFAULT (GETDATE())
);

示例合并:

MERGE sample_auto_update_log WITH (HOLDLOCK) AS t
USING #changes AS s
ON (t.id = s.id AND t.item_a_before = s.item_a_before AND t.item_a_after = s.item_a_after)
WHEN MATCHED THEN
    UPDATE
    SET update_count = update_count + 1, update_datetime = GETDATE()
WHEN NOT MATCHED THEN
    INSERT (id, item_a_before, item_a_detail, item_a_after)
    VALUES (s.id, s.item_a_before, s.item_a_detail, s.item_a_after);

SQL Fiidle

问题: 如何使用索引或其他方法最好地优化 MERGE?

考虑以下方法。

在更新你的数据的过程中做简单的快速INSERT进入auto_update_log。在此阶段不关心 auto_update_log 中的重复项。

有另一个后台进程周期性地(每隔几分钟,或者任何你系统的 suitable)总结在 auto_update_log 中积累的内容并更新最终的 log table 带有没有重复的简明摘要。使用 MERGE 使用适当的支持索引更新摘要。将 auto_update_log 添加到摘要后对其进行清理。

换句话说,auto_update_log 成为一个临时阶段 table,允许批量更新摘要。摘要中的信息会有延迟,所以你需要决定是否接受table。


根据您在问题中提出的示例 MERGE 语句,我会考虑在 (id, item_a_before, item_a_after) 上添加索引 - 那些用于比较的字段。或者仅在 id 加上 item_a_before, item_a_after 作为包含的列。在 tables auto_update_log 和你的温度 table #changes.

拥有索引可以加快查找必须更新的行的过程,但是在添加行时更新索引本身需要时间。因此,最终,您需要尝试衡量不同方法的性能。