如何使用多列索引优化 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);
问题:
如何使用索引或其他方法最好地优化 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
.
拥有索引可以加快查找必须更新的行的过程,但是在添加行时更新索引本身需要时间。因此,最终,您需要尝试衡量不同方法的性能。
我是 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
.
示例日志 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);
问题: 如何使用索引或其他方法最好地优化 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
.
拥有索引可以加快查找必须更新的行的过程,但是在添加行时更新索引本身需要时间。因此,最终,您需要尝试衡量不同方法的性能。