SQL Server에서 인덱스 재 구축 속도 향상


9

대량의 데이터를 빈 데이터베이스로 가져오고 있는데 시작하기 전에 고유하지 않은 비 클러스터형 인덱스를 모두 비활성화하여 가져 오기 성능을 향상시킬 수 있는지 확인했습니다.

이제 색인을 다시 활성화하고 싶습니다.이를 최적화하기 위해 할 수있는 일이 있는지 궁금합니다.

100 개가 넘는 테이블과 거의 2,000 개의 인덱스가 다시 작성됩니다. 데이터베이스 크기는 200GB입니다.

내가 실행중인 스크립트의 핵심 부분은 다음과 같습니다.

declare c_toggle_index cursor FORWARD_ONLY READ_ONLY for
    select  'alter index ' + QUOTENAME(i.name) + ' on ' + o.name + ' rebuild'
    from    sys.indexes as i
    Inner Join sys.objects o
    On o.object_id = i.object_id
    Where o.is_ms_shipped = 0
    And i.index_id >= 1
    and i.type > 1
    and i.is_disabled = 1

alter index 문에 ONLINE = OFF를 설정하는 것을 고려했지만 인덱스가 비활성화 된 것으로 시작하면이 설정이 효과가 있는지 확신 할 수 없었습니다. 또한 SORT_IN_TEMPDB = ON 설정을 고려했지만 tempdb 파일이 데이터베이스의 .mdf 파일과 동일한 드라이브에 있기 때문에 그로 인한 이점도 없다고 가정했습니다.

재 빌드 스크립트를 실행하는 동안 많은 CXPACKET 대기 유형이 있음을 알았습니다. 나는 그것이 왜 그런지 또는 내가 해결해야 할 문제인지 이해하지 못합니다.

관련이있을 수있는 마지막 한 가지 사항 : 데이터베이스로 데이터를 가져 오는 것 외에 현재 전체 서버가 비활성 상태입니다. 고려하거나 걱정할 다른 사용자 활동은 없습니다. 저의 유일한 관심사는 가능한 가장 짧은 시간에 데이터베이스로 데이터를 가져 오는 것입니다.


3
가져 오기 시간 만 관심사라고 할 때 가져 오기 시작부터 인덱스 다시 활성화까지의 시간을 의미합니까? 그렇다면 가져 오는 동안 인덱스를 활성화 된 상태로 두어야합니다. 200GB 데이터에 대한 2,000 개의 인덱스는 나에게 많은 인덱스처럼 들립니다. 어쩌면 인덱스 사용법 DMV를보고 제거 할 수있는 것이 있는지 확인해야합니다.
Max Vernon

1
명확히하기 위해 한 번이 아니라 동일한 200GB 가져 오기를 반복해야합니까?
Jon Seigel

1
가져 오기를 한 번만 수행하면되지만 제한된 시간 동안 더 큰 프로세스의 일부로 현재 해당 프로세스를 테스트하여 해당 창에 맞도록 테스트하고 있습니다. @MaxVernon 인덱스를 활성화 상태로 두는 것이 가장 빠른 방법 인 것 같습니다. 일반적으로 인덱스를 비활성화하고 데이터를 가져온 다음 인덱스를 다시 활성화하는 것이 더 빠르다는 것에 놀랐습니다. 이 데이터베이스는 타사 데이터베이스이므로 인덱스를 제거하거나 달리 변경할 수 없습니다.
paulH

3
괜찮아. CXPACKET대기 정보 : 인덱스 재 구축 자체는 인덱스 검색 (심지어 재 구축 중인 인덱스도 )하며 이러한 스캔은 병렬 처리를 사용할 수 있습니다. 이러한 대기에 대해 걱정하지 않아도됩니다. 병렬 처리가 도움이 될 수 있습니다.
Jon Seigel

답변:


10

이 시나리오에서 최적의 가져 오기 성능을 달성하려면 다음 세 가지가 필요합니다.

  1. 최소한으로 기록 된 기본 테이블 인서트
  2. 최소한으로 기록 된 비 클러스터형 인덱스 빌드
  3. 물리적 읽기 방지

최소 로깅

비 클러스터형 인덱스없이 빈 클러스터 된 테이블에 최소 로깅 된 삽입을 달성 하려면 다음이 필요합니다.

  1. 중 하나를 사용 SIMPLE하거나 BULK_LOGGED데이터베이스 복구 모델을
  2. 테이블 잠금 및 주문 입력을 지정 (예 TABLOCKORDER힌트)

사이드 노트 :

추적 플래그 610이 사용 가능한 경우 비 클러스터형 인덱스가있는 클러스터 된 테이블에 최소 로깅 된 삽입을 달성 할 수도 있습니다. 비 클러스터형 인덱스 삽입이 최소한으로 기록되는지 여부는 쿼리 최적화 프로그램에서 선택한 쿼리 계획에 따라 다릅니다.

쿼리 계획은 비 클러스터형 인덱스에 대해 별도의 반복자를 사용하는 경우 반복자는이 DMLRequestSort에 대한 속성 집합을 true, 클러스터되지 않은 인덱스 삽입은 최소한됩니다 다른 조건이 이미 충족 언급 제공, 기록.

비 클러스터형 인덱스를 별도로 빌드

이 작업의 장점은 다음과 같습니다.

  1. TF 610을 활성화하지 않고도 클러스터형 인덱스 삽입을 최소화 할 수 있습니다.
  2. CREATE INDEX 복구 모델이 아닌 경우 최소 기록 FULL

물리적 읽기 방지

이상적으로는 가져올 데이터는 별도의 머신에 저장되거나 데이터베이스를 호스팅하는 데 사용 된 것과는 별도의 물리적 스토리지에 저장됩니다.

데이터베이스 서버에는 가장 큰 기본 테이블을 캐시에 보관할 수있는 충분한 메모리가 있어야하며 비 클러스터형 인덱스를 작성할 때 필요한 정렬 작업에 충분한 공간이 있어야합니다.

좋은 패턴은 기본 테이블 (최소 로그 된 클러스터 된 인덱스로드)을 빠르게로드 한 다음 해당 데이터 페이지가 계속 캐시되는 동안 해당 테이블에 대한 모든 비 클러스터형 인덱스를 작성하는 것입니다.

이 질문은 기본 테이블을 먼저로드 한 다음 클러스터되지 않은 인덱스를 작성하는 프로세스를 간략하게 설명합니다. 커서 정의 ORDER BY 동일한 테이블에서 클러스터되지 않은 인덱스 빌드를 그룹화 하기 위해 사용하지 않습니다 .

다른 테이블에 대한 데이터 페이지를 반복해서 캐시로 읽은 다음 비 클러스터형 인덱스가 비 결정적 순서로 구축되면 삭제 될 가능성이 있습니다 .

반복적 인 물리적 읽기 비용은 클러스터되지 않은 인덱스를 별도로 구축함으로써 얻는 최소 로깅의 이점을 완전히 지배합니다. 이는 다음 표로 이동하기 전에 주어진 표에 대한 모든 비 클러스터형 색인이 유지되기 때문에 기존 색인이있는 표를 더 빨리로드하는 이유를 설명합니다.

요약

한 번에 하나의 테이블을 대량로드하려면 가져 오기 프로세스를 재 작업해야합니다. 이는 다음으로 이동하기 전에 테이블을로드하고 모든 비 클러스터형 인덱스를 작성하는 것을 의미합니다. SQL Server 인스턴스는 가장 큰 테이블을 보유 할 수있는 충분한 메모리가 있어야 하고 동시에 최대 규모의 클러스터되지 않은 인덱스 정렬을 수행합니다.

당신은 할 수 이미 자리에 클러스터되지 않은 인덱스가있는 테이블로 데이터를로드하기 전에 TF (610)을 가능하게하려고합니다. 일반적으로 이전 방법만큼 빠르지는 않지만 충분히 빠를 수 있습니다.

자세한 내용은 다음을 참조하십시오.

데이터 로딩 성능 안내서

최소한으로 기록 할 수있는 작업

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.