转换SELECT查询为DELETE语句,精简数据库仅保留指定ModelID数据
将SELECT查询转成反向DELETE语句(精简大表数据)
先明确要保留的数据范围
原SELECT语句留下的是两类数据:
MODEL_GROUP_MEMBER(以下简称MGM)里MODEL_ID = '149839'的所有记录PARTS_TABLE(以下简称PT)里满足两个条件的记录:一是MODEL_GROUP_CODE能匹配到MGM中MODEL_ID='149839'的行,二是HDRDESC不为空
我们要做的就是删除所有不属于这个范围的数据,分两张表处理,而且因为PT是超4000万行的大表,必须考虑性能,不能硬删。
处理MODEL_GROUP_MEMBER的删除
1. 直接删除(小表用,大表别这么干)
如果MGM数据量不大,可以直接删非目标ID的行:
USE SMR_UK_DATA; DELETE FROM dbo.MODEL_GROUP_MEMBER WHERE MODEL_ID != '149839';
2. 分批删除(大表必用,避免锁表卡死)
要是MGM数据也不少,就每次删一部分,循环直到删完:
USE SMR_UK_DATA; WHILE 1=1 BEGIN -- 每次删1万行,可根据服务器性能调数字 DELETE TOP (10000) FROM dbo.MODEL_GROUP_MEMBER WHERE MODEL_ID != '149839'; -- 没行可删就退出循环 IF @@ROWCOUNT = 0 BREAK; END;
处理PARTS_TABLE的删除
这张表是核心大表,必须谨慎操作,先把要保留的记录标记出来再删。
方法1:关联删除(数据量小的时候用)
直接通过关联筛选要删的行,但大表这么干可能慢到离谱:
USE SMR_UK_DATA; DELETE PT FROM dbo.PARTS_TABLE PT LEFT JOIN dbo.MODEL_GROUP_MEMBER MGM ON PT.MODEL_GROUP_CODE = MGM.MODEL_GROUP_CODE AND MGM.MODEL_ID = '149839' -- 要么没匹配到目标MGM的记录,要么HDRDESC为空 WHERE MGM.MODEL_GROUP_CODE IS NULL OR PT.HDRDESC IS NULL;
方法2:分批删除(大表首选)
先把要保留的PT记录的主键(比如PART_ID,换成你实际的主键/唯一列)存临时表,再分批删不在临时表里的行:
USE SMR_UK_DATA; -- 第一步:把要保留的PT记录的唯一标识存到临时表 SELECT PT.PART_ID -- 替换成PT表的主键或唯一列 INTO #KeepParts FROM dbo.PARTS_TABLE PT JOIN dbo.MODEL_GROUP_MEMBER MGM ON PT.MODEL_GROUP_CODE = MGM.MODEL_GROUP_CODE WHERE MGM.MODEL_ID = '149839' AND PT.HDRDESC IS NOT NULL; -- 第二步:循环分批删除不需要的行 WHILE 1=1 BEGIN DELETE TOP (10000) FROM dbo.PARTS_TABLE WHERE PART_ID NOT IN (SELECT PART_ID FROM #KeepParts); -- 对应上面的列 IF @@ROWCOUNT = 0 BREAK; END; -- 第三步:用完临时表删掉 DROP TABLE #KeepParts;
重要提醒
- 先备份!先备份!先备份! 删数据前必须全量备份数据库,删错了能救回来。
- 调分批行数:
TOP (10000)这个数字根据你服务器的CPU、内存调整,别一次删太多导致服务器卡死。 - 检查索引:确保MGM的
MODEL_ID、PT的MODEL_GROUP_CODE和HDRDESC有合适的索引,能大幅提升删除速度。 - 事务可选:如果要保证数据一致,可以在循环里加事务,但会增加锁表时间,自己权衡。
内容的提问来源于stack exchange,提问作者user2317446
相关产品推荐
相关产品推荐

