我有源视图,用于填充目标表。我最近向视图添加了 2 个新列,因此将它们包含到现有的 HASHBYTES 函数中。这是新的 content_hash 在视图中的样子:
CONVERT(NVARCHAR(100), HASHBYTES('SHA2_512',
CONCAT(ISNULL(CONVERT(VARCHAR(30), FORMAT(tl.[TRANSACTION_ID],'#')), 'NULL TRANSACTIONUID'), '|'
,ISNULL(CONVERT(VARCHAR(30), FORMAT(tl.[COMPANY_ID],'#')), 'NULL PROJECTUID'), '|'
,ISNULL(CONVERT(VARCHAR(30), FORMAT(tl.[DEPARTMENT_ID],'#')), 'NULL OPERATINGGROUPUID'), '|'
,ISNULL(CONVERT(VARCHAR(30), FORMAT(d.[DEPARTMENT_ID],'#')), 'NULL SO_OPERATINGGROUPUID'), '|' --added per User Story #4626
,ISNULL(CONVERT(VARCHAR(50),cx.modifiedon), 'NULL IV_MODIFIEDON'), '|' --added per User Story #4652
,ISNULL(CONVERT(VARCHAR(30), FORMAT(tl.[OPENAIR_IS_PERSON_ID],'#')), 'NULL RESOURCEUID'), '|'
,ISNULL(CONVERT(VARCHAR(30), FORMAT(tl.[SUBSIDIARY_ID],'#')), 'NULL LEGALENTITYUID'), '|'
,ISNULL(CONVERT(VARCHAR(30), FORMAT(tl.[ACCOUNT_ID],'#')), 'NULL GLACCOUNTUID'), '|'
,ISNULL(CONVERT(VARCHAR(30), FORMAT(tl.[CLASS_ID],'#')), 'NULL GLCLASSUID'), '|'
,ISNULL(CONVERT(VARCHAR(30), FORMAT(c.[PARENT_ID],'#')), 'NULL CLIENTUID'), '|'
,ISNULL(CONVERT(VARCHAR(30), a.[TYPE_NAME]), 'NULL GLACCOUNTTYPEUID'), '|'
,ISNULL(CONVERT(VARCHAR(30), FORMAT(t.[TRANDATE],'YYYYMMDD')), 'NULL TRANDATE'), '|'
,ISNULL(CONVERT(VARCHAR(30), FORMAT(tl.[AMOUNT],'#.############')), 'NULL AMOUNT'), '|'
,ISNULL(CONVERT(VARCHAR(30), FORMAT(tl.[AMOUNT_LINKED],'#.############')), 'NULL AMOUNT'), '|'
,ISNULL(CONVERT(VARCHAR(30), FORMAT(tl.[AMOUNT_PENDING],'#.############')), 'NULL AMOUNT'), '|'
,ISNULL(CONVERT(VARCHAR(30), [NON_POSTING_LINE]), 'NULL NONPOSTINGLINE'), '|'
,ISNULL(CONVERT(VARCHAR(30), tl.[OPENAIR_ITEM_DESCRIPTION]), 'NULL Desc'), '|'
,ISNULL(CONVERT(VARCHAR(30), FORMAT(tl.[DATE_CREATED],'yyyyMMdd HH:MM:ss')), 'NULL TRANDATE'), '|'
,ISNULL(CONVERT(VARCHAR(30), FORMAT(tl.[DATE_LAST_MODIFIED_GMT],'yyyyMMdd HH:MM:ss')), 'NULL LAST_MODIFIED')
)))
as content_hash
我遇到的问题是运行更新,将目标表content_hash设置为视图中content_hash的结果。更新只是无限期地运行并且永远不会完成(我已经让它运行了长达 2 小时)。
UPDATE tgt
SET
tgt.content_hash = src.content_hash
FROM dbo.[gl_transaction_line] tgt
INNER JOIN dbo.src_gl_transaction_line src
ON tgt.gl_transaction_line_uid = src.gl_transaction_line_uid
View的结果集大约有646万条记录。单独运行完整视图大约需要 11-12 分钟,这是添加 2 个新字段之前所花费的时间。
我可以采取什么措施来提高性能,或者可以通过其他方式设置目标表中的 content_hash 以匹配视图?
这只是一次性需求,我需要更新整个表中的 content_hash。这是因为我们不希望通常在晚上加载目标表的存储过程看到所有这些 content_hash 差异并将其捕获到历史表中。目标表通常是临时的,但我暂时将其恢复为非临时的以进行这些(隐形)更新,然后重新启用它,否则我们的历史记录大小将加倍,因为每条记录都会被添加这两个新记录所触及领域。
编辑 我在我工作的环境中拥有有限的权限,但我会分享我能分享的内容,并在可以获得的情况下发布更多内容。
一般来说,我们的仓库中有存储过程,它们作为夜间刷新的一部分执行。这些 Sp 将源视图与其目标时态表进行比较,以确定是否应该发生插入、更新、删除或“无任何操作”。我将分享相关 sp 的开头片段,但这就是我们使用 content_hash 的原因。如果有更好的方法来解决这一切,我会洗耳恭听。我对这个环境还比较陌生,所以我无法解释为什么事情是这样构建的,但我很高兴迭代出更好的解决方案。
IF OBJECT_ID('tempdb.dbo.#processing_path') IS NOT NULL BEGIN DROP TABLE #processing_path END
SELECT ISNULL(src.gl_transaction_line_uid, tgt.gl_transaction_line_uid) as gl_transaction_line_uid
, CASE WHEN tgt.gl_transaction_line_uid IS NULL
THEN 'Insert'
WHEN src.gl_transaction_line_uid IS NULL
THEN 'Delete'
WHEN src.content_hash != tgt.content_hash
THEN 'Update'
ELSE 'Unchanged' END AS processing_path
, tgt.version_begin_timestamp
INTO #processing_path
FROM dbo.src_gl_transaction_line src
FULL JOIN dbo.[gl_transaction_line] tgt ON src.gl_transaction_line_uid = tgt.gl_transaction_line_uid
CREATE UNIQUE CLUSTERED INDEX idx_uc ON #processing_path (gl_transaction_line_uid)
因此,根据分配源视图中的记录的processing_path
,这决定了这些记录是否由 sp 中进一步的 DELETE、UPDATE 或 INSERT 查询处理。
第 1 部分:将数据放入临时表
CREATE TABLE #TempHashes (gl_transaction_line_uid int PRIMARY KEY, content_hash nvarchar(100));
INSERT INTO #TempHashes (gl_transaction_line_uid, content_hash)
SELECT gl_transaction_line_uid, content_hash
FROM dbo.src_gl_transaction_line;
然后只需使用新的哈希值更新原始表,并使用预先计算的哈希值连接 ID。