在我的项目中,我遇到了以下 T-SQL 代码的挑战。
- step1 使用父模块及其订阅用户填充 UserModules 表
- step2 在 Modules_Hierarchy 表中检查与 step1 中的模块关联的子模块,并通过将子模块与父模块订阅的用户映射来将有效记录插入到 UserModules 表中。此步骤将递归重复,直到找到所有子模块。
问题:
在第 2 步中,WHILE 循环和 SELECT 语句使用相关子查询,并且表 UserModules 是 INSERT 和相关 SELECT 子句的一部分,这会妨碍性能,并且查询经常会因以下 LOCK 升级问题而失败。
ModulesUsers 表中的最终数据大小为 4200 万,预计还会增长。
错误消息: “SQL Server 数据库引擎的实例此时无法获取 LOCK 资源。当活动用户较少时重新运行您的语句。请数据库管理员检查此实例的锁和内存配置,或检查长时间运行的事务。”</p>
如何优化此查询,即第 2 步以解决问题?
第1步:
INSERT INTO UserModules(ModuleID, UserID)
SELECT ModuleID, UserID
FROM TABLEA a
INNER JOIN TABLEB b ON a.ID = b.ID
第2步:
DECLARE @cnt int
SET @cnt = 1
WHILE( @cnt > 0 )
BEGIN
SET @cnt = (SELECT COUNT(DISTINCT s.moduleid)
FROM Modules_Hirarchy s WITH (nolock), Modules t
WHERE s.ParentModuleId = t.ModuleId
------------
AND NOT EXISTS
(SELECT ModuleId + EndUserId
FROM UserModules r
WHERE s.moduleid = r.moduleid
AND t.EndUserId = r.EndUserId)
AND s.moduleid + t.EndUserId NOT IN
(SELECT CAST(ModuleId AS varchar) + EndUserId
FROM UserModules ))
IF @cnt = 0
BREAK
INSERT INTO UserModules (ModuleId, EndUserId)
SELECT DISTINCT s.moduleid, t.EndUserId
FROM Modules_Hirarchy s WITH (nolock), UserModules t
WHERE s.ParentModuleId = t.ModuleId
AND NOT EXISTS
(SELECT ModuleId + EndUserId
FROM UserModules r
WHERE s.moduleid = r.moduleid
AND t.EndUserId = r.EndUserId)
END