2010-01-15 7 views
5

입력 한 날짜를 기준으로 큰 (~ 50m 레코드 DB) 행을 삭제하는 아카이브 스크립트를 실행 중입니다. 날짜 필드는 테이블의 클러스터 된 인덱스이므로 조건문을 적용 할 대상입니다.인덱스에 의해 SQL 서버 삭제 속도가 크게 느려짐

이 삭제는 while 루프에서 실행 중이고 배치에서 1000에서 100,000 개의 레코드를 시도합니다. 배치 크기에 관계없이 놀랍도록 느립니다. 10,000 개의 레코드가 삭제되는 것과 같습니다. 실행 계획을 보면 "인덱스 삭제"에 많은 시간을 할애 할 수 있습니다. 테이블에는 약 15 개의 필드가 있으며, 약 10 개의 필드가 있습니다. 이 문제를 해결할 방법이 있습니까? 나는 각 인덱스를 삭제하는 데 너무 오래 걸리는 이유를 모르겠다. 누군가가 여기에서 무슨 일이 일어나고 있는지 밝혀 낼 수 있을까? 나는에 주저 해요 이유입니다,

alt text http://img94.imageshack.us/img94/1006/indexdelete.png

(삭제 명령 시퀀스 점)

이 데이터베이스는 라이브이며, 종종 삽입지고 : 이것은 내 실행 계획의 샘플입니다 크기를 트리밍하는 copy and truncate 메소드를 사용하십시오. 여기에 누락 된 다른 옵션이 있습니까?

+2

이러한 모든 색인이 완전히 필요합니까? 색인을 사용하지 않는다면 색인을 제거해야합니다. –

+0

방금 ​​메인 사이트 프로그래머와 이야기를 나누었습니다. 이제는 더 이상 필요하지 않은 것 같습니다. 테이블에 대해 쿼리를 수행하는 동안 로그 유형 테이블로 사용되는 경우가 더 많습니다. 삭제 스크립트를 다시 실행하기 전에 일부 삽입을 삭제하려고 할 수 있습니다. – Kevin

답변

1

해결 방법이 더 많지만 행을 삭제하는 대신 IsDeleted 플래그를 테이블에 추가하고 1으로 업데이트 할 수 있습니까? 이 플래그를 사용하려면 SELECTsUPDATEs을 수정해야합니다.

그런 다음 시간외로 이러한 레코드를 삭제하거나 보관하도록 예약 할 수 있습니다.

+0

글쎄, 나는이 스크립트를 하루 종일 정기적으로 실행하여 데이터베이스를 지우고 (2 년이 넘은 레코드는 삭제), 초기 실행이 너무 느려서 현재 완료하는 데 4 시간 정도 걸릴 것입니다. 서버를 묶어두기를 원합니다. 그래도 제안에 감사드립니다! – Kevin

+1

그런 경우 최종 사용자 관점에서 서버로드에 지각할만한 영향이 없도록 한 번에 작은 배치 (예 : 1,000)를 삭제하고 각 루프 사이에 30-60 초의 지연으로이를 반복하십시오. 그런 다음 끝날 때까지 실행하십시오. 일주일이나 이틀이 걸릴 수도 있지만 일을 끝내야합니다. – RedFilter

1

SQL Server 2005/2008을 사용중인 경우 테이블을 조사하여 파티션으로 변환해야하는 경우 기존 데이터를 매우 빨리 제거 할 수 있습니다 . '롤링 창'유형 효과를 위해 설계되었으며 테이블/프로세스를 묶는 대규모 삭제를 방지합니다.

불행하게도이 프로덕션의 테이블에서는이 기술로 건너 뛰기 위해이 기술을 업그레이드/마이그레이션하기 위해 T-SQL 코딩, 지식 및 주말이 필요합니다. 일단 기존의 선택 및 삽입이 원활하게 작동하더라도 파티션 유지 관리 및 추가/제거는 프로세스를 제어하기 위해 t-SQL이 필요한 곳입니다.

2

@NickLarsen이 의견으로 제안한 제안보다 두 번째. unused indexes이 있는지 알아보십시오. 이렇게하면 해당 인덱스 삭제의 오버 헤드를 줄일 수 있으므로 작업을보다 신속하게 수행하기에 충분할 수 있습니다.

또 다른 급진적 인 전략은 모두 인덱스를 삭제하고 삭제 한 다음 더 작은 데이터 세트의 인덱스를 빠르게 다시 만드는 것입니다. 이것은 반드시 서비스를 방해하지는 않지만, 그 동안에는 쿼리가 훨씬 느려질 수 있습니다. 필자는 Microsoft SQL Server 전문가는 아니지만이 전략에 대한 조언을 소금 한알로 가져 가야합니다.

3

테이블의 각 레코드에 대해 5 개의 인덱스 레코드가 있다고 가정합니다.

이제 각 삭제는 본질적으로 5 가지 작업입니다.

추가하면 클러스터 된 인덱스가 있습니다. 클러스터 된 인덱스 삭제 시간이 매우 큽니다. (10 배) 다른 색인보다 길어? 이것은 모든 레코드가 삭제 된 상태에서 데이터가 재구성되기 때문입니다.

재사용하는 것보다 대량 인덱스를 삭제하는 것이 좋습니다. 삭제 및 삽입시 인덱스 작업은 본질적으로 많은 비용이 듭니다. 단일 재 구축이 훨씬 더 빠를 가능성이 높습니다.

6

클러스터 된 인덱스 + 클러스터되지 않은 클러스터에서 10k 레코드를 삭제하는 데는 1 분이 걸리지 않습니다. 정말 느린 IO 하위 시스템 인 것 같습니다. 다음에 대한 값은 무엇입니까 :

  • Avg. 디스크 초/쓰기
  • Avg. 디스크 초/읽기
  • 평균. 디스크 쓰기 큐 길이
  • 평균. 디스크 읽기 대기열 길이

작업에 관련된 각 드라이브 (로그 파일 포함)! 인덱스를 별도의 파일 그룹에 배치하고 각 파일 그룹을 고유 한 LUN 또는 자체 디스크에 할당 한 경우 어떤 인덱스가 더 문제가 있는지 식별 할 수 있습니다. 또한 로그 플러시가 주요 병목 일 수 있습니다. SQL Server는 여기에서 많은 통제력을 갖지 못합니다. 모든 것을 손쉽게 속도를 높일 수 있습니다. 그 시간은 CPU 사이클에서 소비되지 않으며 IO가 완료되기를 기다리는 데 소비되며 사용자가 요구하는 부하에 맞게 조정 된 IO 하위 시스템이 필요합니다.

IO로드를 줄이려면 색인을 더 좁게 만드십시오. 주로 클러스터 된 인덱스가 가능한 가장 좁은 인덱스인지 확인하십시오. 그런 다음 비 클러스터형 인덱스에 사용되지 않는 커다란 기둥이 포함되어 있지 않은지 확인하십시오 (필자는 ...). page compression을 사용하면 큰 이득을 얻을 수 있습니다. 그리고 궁극적으로 sys.dm_db_index_usage_stats에서 색인 사용 통계를 검사하고 색인이 도끼에 적합한 지 확인하십시오.

IO로드를 많이 줄일 수없는 경우, 분할하려고 시도해야합니다. 파일 그룹을 데이터베이스에 추가하고, 별도의 파일 그룹에 큰 인덱스를 이동하고, 파일 그룹을 별도의 IO 경로 (별개의 스핀들)에 배치하십시오.

앞으로 정기적으로 삭제 작업을 수행하는 것이 가장 좋은 대안은 파티션 전환을 사용하고 모든 인덱스가 클러스터 된 인덱스 분할과 정렬되도록하고 시간이 다되면 번개 빠른 삭제를 위해 마지막 분할 영역을 삭제하는 것입니다.

+0

나는 하드웨어가 그 이상의 능력을 가지고 있다고 확신한다. 우리는 로그와 데이터를위한 별도의 인텔 SSD와 OS를위한 별도의 인텔 SSD를 가지고 있습니다. 듀얼 제온 쿼드 코어 프로세서와 16Gb DDR3 메모리를 장착하고 있습니다. ~ 25m 행을 정리하기 위해 주말에이 작업을 끝내 었습니다. 이제 DB를 멋지게 유지하기 위해 야간에 실행하고 1 ~ 2 분 정도 소요됩니다. – Kevin

+8

측정 할 생각조차 없다고 확신합니까? –

관련 문제