【发布时间】:2021-12-04 20:37:50
【问题描述】:
我正在尝试将数百万行插入/更新到已经包含数百万行的表中。
目标表包含一个 ID 列 (PK) 和许多其他列。
我正在将 csv 中的数据插入临时表 #temp(与目标表相同的列,除了 ID)。
然后我尝试合并它们,但合并速度非常慢(10M 行需要几个小时)。
-- Create temporal table #temp with almost all the columns in target_table
SELECT ColumnA,
ColumnB,
ColumnC,
ColumnD,
ColumnE,
ColumnF,
ColumnG,
ColumnH
INTO #temp
FROM target_table
WHERE 1 = 2;
<HERE I DO A BULK INSERT INTO #temp WHICH ONLY TAKES A FEW SECONDS>
-- -- Merge into target_table
MERGE target_table AS TARGET
USING #temp AS SOURCE
ON (
TARGET.ColumnA = SOURCE.ColumnA
AND
TARGET.ColumnB = SOURCE.ColumnB
AND
TARGET.ColumnC = SOURCE.ColumnC
AND
TARGET.ColumnE = SOURCE.ColumnE
)
WHEN MATCHED
AND (
(TARGET.ColumnG IS NULL AND SOURCE.ColumnG IS NOT NULL OR TARGET.ColumnG <> SOURCE.ColumnG)
OR
(TARGET.ColumnH IS NULL AND SOURCE.ColumnH IS NOT NULL OR TARGET.ColumnH <> SOURCE.ColumnH)
)
THEN
UPDATE SET TARGET.ColumnG = SOURCE.ColumnG, TARGET.ColumnH = SOURCE.ColumnH
WHEN NOT MATCHED BY TARGET
THEN
INSERT (ColumnA, ColumnB, ColumnC, ColumnD, ColumnE, ColumnF, ColumnG, ColumnH)
VALUES (SOURCE.ColumnA, SOURCE.ColumnB, SOURCE.ColumnC, SOURCE.ColumnD, SOURCE.ColumnE, SOURCE.ColumnF,
SOURCE.ColumnG, SOURCE.ColumnH);
在批量插入之后,MERGE 的执行计划有一些非常昂贵的排序(占总成本的 41%)。
关于如何加快合并的任何建议?
谢谢!
【问题讨论】:
-
请将您的表和索引定义添加到您的问题中,并通过brentozar.com/pastetheplan 分享查询计划,否则我们无法提供任何明确的帮助。您可能希望在两个表上都有一个聚集索引
(ColumnA, ColumnB, ColumnC, ColumnE) -
什么是相对的“百万”?如果您要更新/插入太多以至于几乎所有数据都被重写,那么要考虑的一个选项是完全构建一个新表(
SELECT现有数据,与新数据结合,然后批量插入),然后使用sp_rename或truncate和alter table .. switch完全替换原始表。这是否更快取决于,但是与更复杂的操作相比,批量插入在速度方面很难被击败,并且在停机时间方面也很难被击败。
标签: sql sql-server indexing merge sqlperformance