2014-06-20 2 views
0

1900 만 레코드가있는 테이블이 있습니다. 중복을 삭제하고 싶지만 사용하고있는 쿼리가 매우 오래 걸리고 결국 연결 시간이 초과됩니다. 많은 양의 행이있는 테이블에서 중복 삭제

내가 사용하고있는 쿼리입니다 : ID는 기본 키 및 자동 증가이다

DELETE FROM [TableName] 
WHERE id NOT IN 
(SELECT MAX(id) FROM [TableName] GROUP BY field) 

. field에서 복제본을 삭제하고 싶습니다.

이 쿼리는 더 빠른 대안이 있습니까?

도움을 주시면 감사하겠습니다.

+2

중복으로 말하면이 링크를 확인하면 도움이됩니다. https://stackoverflow.com/questions/18932/how-can-i-remove-duplicate-rows – g2server

답변

2

나는 속도를 내기 위해 field에 색인을 임시로 추가하는 것이 좋습니다. 어쩌면이 명령문을 사용하여 삭제할 수 있습니다 (색인이 제대로 작동하더라도).

my 문은 삭제해야 할 ID 목록을 생성합니다. id가 기본 키로 인덱싱되었다고 가정하면 이것은 더 빠를 것입니다. 이 또한 not in보다 조금 좋아야합니다.

with candidates as (
    SELECT id 
     , ROW_NUMBER() over (PARTITION by field order by id desc) rn 
     FROM [TableName] 
) 
delete 
    from candidates 
where rn > 1 
+1

'후보자'에 가입하지 않아도됩니다. * 후보자에서 *를 직접 삭제할 수 있습니다. –

+0

@ AndriyM : 고마워요! 내 대답을 편집 할게. –

0

다른 힙 테이블을 만들고 삭제할 ID를 삽입하십시오. 타임 테이블을 피하기 위해 주 테이블 (힙 테이블에 존재)의 레코드를 1000-5000의 덩어리로 삭제하십시오. 행운을 빕니다!

1

내 답변은 논쟁을 피하기 위해 일괄 처리 방식 (작은 대기 시간 포함)으로 Brett Schneiders에서 시작했으며 폭발적인 로그 파일 증가를 완화합니다.

초기 @batchcount을 서버에서 처리 할 수있는 것으로 설정하십시오. 필요에 따라 대기 시간을 늘리거나 줄일 수도 있습니다. @@ROWCOUNT=0이되면 루프가 종료됩니다.

declare @batchcount int, @totalrows int 
set @totalrows = 0 
set @batchcount = 10000 -- set this to some initial value 

while @batchcount > 0 
begin 
    ;with dupes as (
     SELECT id 
      , ROW_NUMBER() over (PARTITION by field order by id desc) rownum 
      FROM [TableName] 
    ) 
    delete top (@batchcount) t1 
     from TableName t1 
     join dupes c 
     on c.id = t1.id 
     and c.rownum > 1 

    set @batchcount = @@ROWCOUNT --record how many just got nuked 
    set @totalrows = @totalrows + @batchcount --track progress 
    print cast(@totalrows as varchar) + ' rows have been deleted' -- show progress 
    waitfor delay '00:00:05' -- wait 5 seconds for log writes, other queries etc 
end 

인쇄 문 ... 인내심을하지 SSMS의 모든 루프의 "쇼"하지만 모든 너무 자주 사용하면 SQL 메시지가 완료된 반복의 수백을 보여주는 표시 볼 수 있습니다.

관련 문제