performance - 允许使 SQL 中的 MERGE 操作更快地工作的方法
问题描述
您能否推荐一些可以使 SQL 中的 MERGE 操作更快地工作的方法?
我认为这个问题完全是关于知识和经验的,不应该被认为是基于意见的,因为任何可以使操作更快的东西绝对适合这个问题,操作越快,答案就越好。
在我的特定情况下,我有大约 170 万条记录,我在重复性工作中获取这些记录,并使用这些记录来更新现有记录。为了[LegalContractors]
尽可能少地锁定真实表(它是),我使用了一个临时表(它是[LegalContractorTemps]
),我将非 SQL(但 C#)代码中的所有记录添加到其中,然后运行MERGE
.
这是我正在尝试的:
DELETE FROM [dbo].[LegalContractorTemps] WHERE [Code] IS NULL;
DELETE FROM [dbo].[LegalContractorTemps]
WHERE [Id] IN (
SELECT [Id]
FROM [dbo].[LegalContractorTemps] [Temp]
JOIN (
SELECT [Code], [Status], MAX([Id]) as [MaxId]
FROM [dbo].[LegalContractorTemps]
GROUP BY [Code], [Status]
HAVING COUNT([Id]) > 1
) [TempGroup]
ON ([Temp].[Code] = [TempGroup].[Code] AND [Temp].[Status] = [TempGroup].[Status] AND [MaxId] != [Id])
);
CREATE UNIQUE INDEX [CodeStatus]
ON [dbo].[LegalContractorTemps] ([Code], [Status]);
SELECT GETDATE() AS [beginTime];
MERGE [dbo].[LegalContractors] AS TblTarget
USING [dbo].[LegalContractorTemps] AS TblSource
ON (TblSource.[Code] = TblTarget.[Code] AND TblSource.[Status] = TblTarget.[Status])
WHEN NOT MATCHED BY TARGET THEN
INSERT ([Code], [ShortName], [Name], [LegalAddress], [Status], [LastModified])
VALUES (TblSource.[Code], TblSource.[ShortName], TblSource.[Name], TblSource.[LegalAddress], TblSource.[Status], GETDATE())
WHEN MATCHED AND
(TblTarget.[ShortName] != TblSource.[ShortName] OR
TblTarget.[Name] != TblSource.[Name] OR
TblTarget.[LegalAddress] != TblSource.[LegalAddress]) THEN
UPDATE SET
TblTarget.[ShortName] = TblSource.[ShortName],
TblTarget.[Name] = TblSource.[Name],
TblTarget.[LegalAddress] = TblSource.[LegalAddress],
TblTarget.[LastModified] = GETDATE()
WHEN NOT MATCHED BY SOURCE THEN
DELETE;
SELECT GETDATE() AS [endTime];
DROP INDEX [CodeStatus] ON [dbo].[LegalContractorTemps];
现在上面显示的代码运行大约 2 分钟。
我找到了这个答案,但我无法将它应用到我的案例中,因为我需要该WHEN NOT MATCHED
子句并且无论如何我都必须执行完整扫描(无论我是否会使用MERGE
)。
解决方案
我会考虑做一个修改后的冲洗和填充,而不是做一个MERGE
。
我最成功的方法是使用分区切换。您构建了三个相同的表;用户从中提取的主表、用于应用CRUD
操作的临时表以及仅在更新后的过渡期间使用的暂存表。
这将需要一些重新工具来将您的LastModified
逻辑直接转移到CRUD
您在更新期间执行的操作中。
然后,在暂存表准备好黄金时间后,截断昨天的暂存表副本。接下来,将数据从主表切换到现在为空的保留表。将数据从 staging 切换到 main。可能将所有这些包装在显式事务中。
繁荣。您的表是最新的。并且您在保留表中有昨天数据的备份副本,以防万一。
这些文章中有大量额外的细节:
推荐阅读
- c# - 本地 dll 和 nuget lib 之间奇怪的 C#.Net 依赖关系
- maven - Liquibase:如何根据配置动态包含来自 github 的文件
- entity-framework - 返回实体框架上的临时表
- html - 我无法理解成功标准 1.3.6:确定目的
- java - 如何创建返回 JSON 的多线程 POST 请求?
- ssl - Netty Echo 服务器/客户端 - SSL 不起作用
- api - Twitter api 将上传的视频关联到媒体库
- opencl - CodeXL 在 clCreateContext 期间崩溃
- c# - 不调用控制器方法
- python-3.x - Ple包安装后不反映