SQL Server: 색인을 안전하게 변경하는 방법

배경



SQL Server는 인덱스에 열을 추가하는 명령을 제공하지 않습니다.
문서 에는, 이하의 기재가 있습니다.


그러므로
create index IX_Table1 on Table1 (
  col1,
  col2
)

위의 인덱스에 col3을 추가하려면 다음과 같이 DROP+CREATE해야 합니다.
drop index IX_Table1 on Table1

create index IX_Table1 on Table1 (
  col1,
  col2,
  col3
)

다만, 이 방법이라면 일시적으로 필요한 인덱스가 없어져 버립니다.
따라서 프로덕션 환경에서 대량으로 쿼리를 실행하는 상황이라면 CPU 부하가 급증할 위험이 있습니다.

다른 방법으로는 인덱스를 별명으로 만들고 이전 인덱스를 DROP하는 방법도 있습니다.
create index IX_Table1_2 on Table1 (
  col1,
  col2,
  col3
)

drop index IX_Table1 on Table1

이 방법을 사용하면 필요한 인덱스가 사라지지 않으므로 일시적인 성능 저하를 방지할 수 있습니다.
그러나 인덱스 이름이 바뀌기 때문에 힌트 절에서 인덱스를 직접 지정한 쿼리가 실행 중이면 오류가 발생합니다.



그 때문에, 영향 범위의 사전 조사가 필요할 경우가 있어, 귀찮습니다.

아래와 같이, 최초의 안을 명시적인 트랜잭션으로 둘러싸면, 인덱스 힌트를 사용하고 있었다고 해도 에러가 되지는 않습니다만, create index가 끝날 때까지 블록 되어 계속해 버립니다. 따라서, 테이블의 레코드 사이즈가 큰 경우는 블로킹 시간이 몇분~수 충분히 되어 버리는 일도 있기 때문에 그다지 좋은 방법이라고는 할 수 없습니다.
begin tran
  drop index IX_Table1 on Table1

  create index IX_Table1 on Table1 (
    col1,
    col2,
    col3
  )
commit tran

해결 방법


--まず、新しいインデックスを作成する
create index IX_Table1_2 on Table1 (
  col1,
  col2,
  col3
) with(online=on) --enterprise edition または sql database ならオンライン操作可能

--次に、同一トランザクション内で、不要インデックスのDROPと、新しいインデックスを同じ名前にrenameする処理を実施
begin tran
  drop index IX_Table1 on Table1
  exec sp_rename 'Table1.IX_Table1_2', 'IX_Table1'
commit tran

위의 쿼리라면 drop index도 sp_rename도 레코드 크기에 관계없이 순식간에 완료하는 처리이기 때문에 약간의 시간만 잠금을 유지하지만 인덱스의 이름을 동일하게 유지한 채 인덱스를 구성하는 열을 변경할 수 있습니다.

※참고로서, 초간 300 액세스 정도의 테이블에 대해서 이번의 방법을 실시했는데, 잘 작동했습니다.
그러나 몇 초 이상 걸리는 쿼리로 액세스하면 차단이 발생할 가능성이 높으므로 주의해야 합니다.

좋은 웹페이지 즐겨찾기