请求优化含NOT IN子句的MSSQL插入查询
MSSQL 查询优化方案
优化后的查询写法
方案1:使用NOT EXISTS替代NOT IN
NOT EXISTS采用半连接逻辑,找到匹配项即停止遍历,大表场景下性能比NOT IN更稳定,还能避免NOT IN遇到NULL值时的意外过滤问题:
INSERT INTO dbo.tblLabOrderNameMaster ( Labpanelcdname, labtestcdabbr, Status, AppDateCreated, AppDateModified, UserId ) SELECT TestName, Test, 1, GETDATE(), GETDATE(), 1 FROM dbo.tblLabsDrawImport li WITH(NOLOCK) WHERE NOT EXISTS ( SELECT 1 FROM dbo.tblLabOrderNameMaster lom WITH(NOLOCK) WHERE lom.Status = 1 AND lom.Labpanelcdname = li.TestName )
方案2:使用LEFT JOIN + IS NULL
该写法逻辑与NOT EXISTS等价,执行计划通常一致,部分开发者会觉得可读性更好:
INSERT INTO dbo.tblLabOrderNameMaster ( Labpanelcdname, labtestcdabbr, Status, AppDateCreated, AppDateModified, UserId ) SELECT li.TestName, li.Test, 1, GETDATE(), GETDATE(), 1 FROM dbo.tblLabsDrawImport li WITH(NOLOCK) LEFT JOIN dbo.tblLabOrderNameMaster lom WITH(NOLOCK) ON lom.Labpanelcdname = li.TestName AND lom.Status = 1 WHERE lom.Labpanelcdname IS NULL
索引优化建议
索引是提升查询性能的核心,针对你的表结构建议创建以下索引:
- 在
tblLabOrderNameMaster上创建复合索引,覆盖子查询的过滤与匹配条件,避免表扫描或键查找:CREATE NONCLUSTERED INDEX IX_tblLabOrderNameMaster_Status_Labpanelcdname ON dbo.tblLabOrderNameMaster (Status, Labpanelcdname); - 在
tblLabsDrawImport上创建包含所需列的索引,让SELECT语句直接从索引获取数据,无需访问表:CREATE NONCLUSTERED INDEX IX_tblLabsDrawImport_TestName_Test ON dbo.tblLabsDrawImport (TestName) INCLUDE (Test);
额外注意事项
- 谨慎使用
WITH(NOLOCK):该提示会读取未提交的脏数据,仅在业务允许脏读场景下使用;如果需要一致性读,建议开启READ COMMITTED SNAPSHOT ISOLATION替代。 - 分批次插入:如果
tblLabsDrawImport数据量持续增长,建议分批次插入(比如每次插入1000条),避免单事务过大导致日志膨胀或锁表时间过长。
内容的提问来源于stack exchange,提问作者Sup Ravi Kumar
相关产品推荐
相关产品推荐

