SQL Server에서 100만 행 삭제
나는 고객의 데이터베이스에서 작업 중인데 소프트웨어 버그로 인해 삭제해야 할 행이 약 100만 개 있습니다.다음 외에 이러한 항목을 효율적으로 삭제할 수 있는 방법이 있습니까?
DELETE FROM table_1 where condition1 = 'value' ?
위에서 제안한 바와 같이 일괄 삭제를 위한 구조입니다.한 번에 1M을 시도하지 마십시오...
배치의 크기와 지연 대기 시간은 분명히 매우 다양하며, 서버 기능과 경합을 완화해야 하는 필요성에 따라 달라집니다.일부 행을 수동으로 삭제하여 시간을 측정하고 배치 크기를 서버가 처리할 수 있는 수준으로 조정해야 할 수 있습니다.위에서 언급한 바와 같이, 5000이 넘으면 잠금이 발생할 수 있습니다(제가 미처 알지 못했습니다).
이 일은 근무 시간 이후에 하는 것이 최선일 것입니다.그러나 SQL이 처리하기에는 1M 행이 많지 않습니다.SSMS에서 메시지를 보는 경우 인쇄 출력이 표시되는 데 시간이 걸릴 수 있지만 몇 번의 배치 후에는 실시간으로 업데이트되지 않습니다.
편집: 중지 시간이 추가되었습니다.@MAXRUNTIME
&@BSTOPATMAXTIME
설정하는 경우@BSTOPATMAXTIME
1까지, 스크립트는 원하는 시간에 자체적으로 중지됩니다(예: 8:00).이렇게 하면 밤 12시에 시작하도록 예약할 수 있으며 오전 8시에 생산되기 전에 중지됩니다.
편집: 답변이 꽤 인기가 많아서 추가했습니다.RAISERROR
대신에PRINT
평당
DECLARE @BATCHSIZE INT, @WAITFORVAL VARCHAR(8), @ITERATION INT, @TOTALROWS INT, @MAXRUNTIME VARCHAR(8), @BSTOPATMAXTIME BIT, @MSG VARCHAR(500)
SET DEADLOCK_PRIORITY LOW;
SET @BATCHSIZE = 4000
SET @WAITFORVAL = '00:00:10'
SET @MAXRUNTIME = '08:00:00' -- 8AM
SET @BSTOPATMAXTIME = 1 -- ENFORCE 8AM STOP TIME
SET @ITERATION = 0 -- LEAVE THIS
SET @TOTALROWS = 0 -- LEAVE THIS
WHILE @BATCHSIZE>0
BEGIN
-- IF @BSTOPATMAXTIME = 1, THEN WE'LL STOP THE WHOLE JOB AT A SET TIME...
IF CONVERT(VARCHAR(8),GETDATE(),108) >= @MAXRUNTIME AND @BSTOPATMAXTIME=1
BEGIN
RETURN
END
DELETE TOP(@BATCHSIZE)
FROM SOMETABLE
WHERE 1=2
SET @BATCHSIZE=@@ROWCOUNT
SET @ITERATION=@ITERATION+1
SET @TOTALROWS=@TOTALROWS+@BATCHSIZE
SET @MSG = 'Iteration: ' + CAST(@ITERATION AS VARCHAR) + ' Total deletes:' + CAST(@TOTALROWS AS VARCHAR)
RAISERROR (@MSG, 0, 1) WITH NOWAIT
WAITFOR DELAY @WAITFORVAL
END
BEGIN TRANSACTION
DoAgain:
DELETE TOP (1000)
FROM <YourTable>
IF @@ROWCOUNT > 0
GOTO DoAgain
COMMIT TRANSACTION
어쩌면 우리 디만트의 이 해결책이
WHILE 1 = 1
BEGIN
DELETE TOP(2000)
FROM Foo
WHERE <predicate>;
IF @@ROWCOUNT < 2000 BREAK;
END
(링크: https://social.msdn.microsoft.com/Forums/sqlserver/en-US/b5225ca7-f16a-4b80-b64f-3576c6aa4d1f/how-to-quickly-delete-millions-of-rows?forum=transactsql)
제가 사용한 것은 다음과 같습니다.
나쁜 데이터가 좋은 데이터와 섞이면,
INSERT INTO #table SELECT columns FROM old_table WHERE statement to exclude bad rows TRUNCATE old_table INSERT INTO old_table SELECT columns FROM #table
이것이 얼마나 좋을지는 모르겠지만 아래와 같이 하면 어떨까요(제공).table_1
독립 실행형 테이블입니다. 즉, 다른 테이블에서 참조하지 않습니다.)
의 복제 테이블 생성
table_1
맘에 들다table_1_dup
insert into table_1_dup select * from table_1 where condition1 <> 'value';
drop table table_1
sp_rename table_1_dup table_1
복구하는 동안 데이터베이스를 운영 환경에서 사용할 수 없는 경우에는 소규모 일괄 작업을 수행합니다.참고 항목:500,000개 이상의 행 테이블에서 잘라내기 테이블을 사용하지 않는 동안 행을 효율적으로 삭제하는 방법
급하고 가능한 한 빠른 방법이 필요한 경우:
- 데이터베이스 운영 중단
- 모든 비관측 인덱스 및 트리거 삭제
- 레코드 삭제(또는 대부분의 레코드가 불량인 경우 복사+드롭+테이블 삭제)
- (해당되는 경우) 트리거를 삭제하여 발생한 불일치 수정
- 인덱스 및 트리거 다시 만들기
- 데이터베이스를 운영 환경으로 되돌립니다.
언급URL : https://stackoverflow.com/questions/24785439/deleting-1-millions-rows-in-sql-server
'programing' 카테고리의 다른 글
"다른 사용자가 이 장치에 호환되지 않는 버전을 이미 설치했으므로 이 앱을 설치할 수 없습니다." (0) | 2023.08.09 |
---|---|
속편화를 사용하는 노드 앱을 어떻게 구성합니까? (0) | 2023.08.09 |
Angular2의 (키업) 옵션은 무엇입니까? (0) | 2023.08.09 |
INSTR과 LIKE 중 어느 것이 더 빠릅니까? (0) | 2023.08.09 |
날짜별 행 크기 찾기 (0) | 2023.08.09 |