24.2. 정기적인 인덱스 다시 만들기

REINDEX 명령을 이용하거나, 이 작업과 상응하는 일련의 작업을 통해 주기적으로 인덱스를 다시 만드는 작업은 몇몇 상황에서는 가치 있는 작업이다.

완전히 빈 B-트리 인덱스 페이지는 재사용 하지만, 해당 페이지에 몇몇 자료를 남기고 대부분 자료가 지워졌다면, 그 인덱스는 전체적으로 과도한 디스크 영역을 사용하게 된다. (이것을 인덱스 팽창(index bloating)이라고 한다. - 옮긴이) 이런 경우 이 인덱스는 검색에서 디스크 읽기 비용이 최적화 된 인덱스보다 당연히 더 든다. (vacuum 작업은 한 페이지의 사용하지 않는 인덱스 로우들을 정리만 하지 그 자료들의 재정렬 작업은 하지 않는다. - 옮긴이) 이런 이유로 주기적인 인덱스 다시 만들기 작업은 서버의 성능을 높일 수 있는 요소가 된다.

B-트리 인덱스가 아닌 경우는 팽창 정도가 얼마나 되는지 구체적으로 알 수 없다. 이 부분은 그 인덱스의 물리적 크기가 어느 정도 커지는지 주기적으로 직접 살펴봐야 한다.

또한 B-트리 인덱스에서는 새로 만든 경우가, 여러번 변경 작업을 한 인덱스보다 순차적인 인덱스 검색 속도가 빠르다. 왜냐하면, 여러번의 변경 작업이 진행되다보면 해당 리프 페이지의 논리적인 순서와 물리적인 순서가 달라지기 때문이다. (이것을 pgstattuple 확장 모듈에서는 단편화라는 용어를 사용해서 그 빈도를 보여준다 - 옮긴이) (B-트리 인덱스가 아닌 인덱스에 대해서는 이 현상이 발생하지 않는다.) 이 부분을 고려해 봐도 주기적으로 인덱스를 새롭게 만드는 방법이 검색 속도를 높이는데 도움을 준다.

인덱스를 다시 새롭게 만드는 가장 손쉬운 방법은 REINDEX 명령을 이용하는 것이다. 하지만, 이 작업은 해당 테이블에 대해서 배타적 잠금을 지정하기 때문에, 새로운 인덱스를 만들고, 옛 인덱스로 바꾸는 여러 작업으로 나누워 진행하는 것이 일반적이다. CREATE INDEX 명령을 사용할 때, 해당 인덱스가 CONCURRENTLY 옵션을 사용 할 수 있다면, 이 옵션을 이용하는 것도 한 방법이다. 새 인덱스가 정상적으로 만들어졌다면, 옛 인덱스를 DROP INDEX 명령으로 지우고, 새 인덱스의 이름을 ALTER INDEX 명령으로 바꾸면 된다. 한편, 인덱스가 유니크나 기본키 제약조건에서 사용된다면, 새로 만들어진 새 인덱스를 ALTER TABLE 명령을 통해서 제약조건 변경 작업을 하고, 옛 인덱스를 지우는 식으로 진행한다. 여기서 소개한 인덱스 다시 만들기 작업은 반드시 각 작업이 정상적으로 진행되지 못했을 경우 복구할 수 있는 방안에 대해서 꼼꼼히 준비해서 작업해야할 것이다.