2009-04-01 4 views
6

두 개의 열에 클러스터 된 인덱스 (테이블의 기본 키)가있는 테이블이 있습니다. 다음과 같이 은 정의됩니다SQL 2005에서 클러스터 된 인덱스 (PK)를 변경하는 가장 좋은 방법

ALTER TABLE Table ADD CONSTRAINT [PK_Table] PRIMARY KEY CLUSTERED 
(
    [ColA] ASC, 
    [ColB] ASC 
)WITH (SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY] 

내가이 클러스터 된 인덱스 PK를 제거하고 다음과 같은 클러스터 된 인덱스를 추가하고 또한 다음과 같이 클러스터되지 않은 인덱스를 사용하여 기본 키 제약 조건을 추가 할 수 있습니다.

CREATE CLUSTERED INDEX [IX_Clustered] ON [Table] 
(
    [ColC] ASC, 
    [ColA] ASC, 
    [ColD] ASC, 
    [ColE] ASC, 
    [ColF] ASC, 
    [ColG] ASC 
)WITH (PAD_INDEX = ON, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF,  DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, FILLFACTOR = 90, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = OFF) ON [PRIMARY] 

ALTER TABLE Table ADD CONSTRAINT 
    PK_Table PRIMARY KEY NONCLUSTERED 
    (
    ColA, 
    ColB 
) WITH(STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 

은 그냥 PK가, 새로운 클러스터 된 인덱스를 추가 한 다음 클러스터되지 않은 기본 키 인덱스를 추가 인덱스를 클러스터 드롭 가고 있었다, 그러나 나는 기존의 클러스터 된 인덱스를 삭제하기로 테이블 데이터를 일으킬 것이라고 배웠습니다 재정렬해야합니다 (대답은 What happens when I drop a clustered primary key in SQL 2005입니다). 필자는 이것이 필요하다고 생각하지 않습니다. 테이블은 1TB를 노크하고 있으므로 불필요한 재주문을 피하고 싶습니다.

내 질문은 기존 구조에서 원하는 구조로 이동하는 가장 좋은 방법은 무엇입니까?

편집 : 그냥 명확히하고 싶습니다. 테이블은 1TB이고 임시 테이블을 생성 할 여유가 없습니다. 임시 테이블을 만들지 않고이를 수행 할 수있는 방법이 있다면 알려주십시오.

답변

8

새 클러스터 된 인덱스를 추가 크기가 1TB에 이르고 행이 많을 수 있으므로 클러스터 된 인덱스를 만드는 것이 좋습니다.

우선 클러스터 된 인덱스를 삭제하고 다시 작성하면 모든 데이터를 적어도 한 번 이상 뒤섞습니다. 그만하면 오래 걸릴 것입니다.

두 번째로, 생성하려는 큰 화합물 클러스터 된 인덱스는 클러스터되지 않은 모든 인덱스의 크기를 크게 늘립니다 (책갈피 조회의 경우 각 리프 노드에 전체 클러스터 된 인덱스 값이 포함되어 있기 때문에).

질문이 더 있습니다. 왜이 작업을하려고합니까? 해당 열이있는 클러스터되지 않은 다른 인덱스를 추가하여 쿼리를 처리 할 수는 없습니까? 왜 이것이 클러스터 된 인덱스 여야합니까 ?? 나는 그 점에 이점이 보이지 않는다 ....

인덱싱 및 특히 클러스터 된 인덱스 토론에 대한 자세한 내용은 SQL Server 인덱스의 Kimberly Tripp's blog - 매우 유용합니다.

마크

4
  1. 새 테이블 만들기 : 테이블

  2. FROM newtable SELECT * INTO

    INSERT :

    CREATE TABLE newtable (colA INT, colB INT) 
    
    • 삽입을 새 테이블로 이전 테이블에서 모든 값

    • 오래된 것을 버리십시오. 테이블 :

      ALTER 표 :

      DROP 표 테이블

    • EXEC의 sp_rename을 'newtable', '테이블'

    • 인덱스를 구축 이전 테이블에 새 테이블의 이름을 바꿉니다 표 추가 제한 PK_Table 기본 키 없음 ( ColA,= OFF WITH 0 COLB ) (STATISTICS_NORECOMPUTE, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON [PRIMARY]

+0

이것은 옵션이 아닙니다. 1.5TB RAID에 1TB 테이블이 있습니다. –

+0

SQL Server에서는 순서 변경 및 이동을 위해 공간이 필요합니다. 공간이 부족한 경우 DROP INDEX에서 MOVE TO 옵션을 사용하여 임시 저장소에 테이블을 만든 다음 RAID에서 다시 작성하십시오. – Quassnoi

+0

행을 청크로 전송하여 이동 중에 소스에서 삭제할 수 있습니다. 그것은 아마도 매우 느린 과정 일 것입니다. –

11

이 귀하의 질문에 대한 완전한 해답이 아니라 확인 ON ALLOW_PAGE_LOCKS = ON) 테이블에 다른 인덱스가 있으면 먼저 인덱스를 삭제합니다. 그렇지 않으면 클러스터 된 인덱스를 제거 할 때 SQL Server에서 모두 다시 빌드해야하며 새 클러스터 된 인덱스를 다시 추가 할 때 다시 빌드해야합니다.일반적인 단계는 다음과 같습니다 테이블 인 경우

  1. 모두 제거 클러스터되지 않은 인덱스는
  2. 제거 클러스터 된 인덱스
  3. 다시 추가 모든 클러스터되지 않은 인덱스
+0

글쎄, 그건 내 계획 이었지만 클러스터 된 인덱스를 제거하는 두 번째 단계는 모든 데이터가 이동되도록합니다. 나는 불필요한 데이터 이동을 피하기 위해 2 단계와 3 단계를 병합하기를 희망했다. –

-1

는 클러스터 인덱스는 실제로 테이블 그 자체에 저장되는 데이터의 실제 순서를 변경하지 마십시오. SQL 6.5 이후로는 이런식이 아닙니다.

페이지의 데이터는 올바른 순서로 저장됩니다. 페이지는 물리적 순서에 상관없이 디스크에 저장 될 수 있습니다.

+0

사실입니까? 나는 데이터의 물리적 인 순서가 클러스터링 키에 의해 결정되었다는 인상을 받았다. –

+0

페이지의 데이터가 올바른 순서로 저장됩니다. 페이지는 물리적 순서에 상관없이 디스크에 저장 될 수 있습니다. – mrdenny

+2

이 구별을 포함하도록 답변을 업데이트 할 수 있습니다. –