1. MySQL (InnoDB)에서 인덱스와 UPDATE
MySQL의 InnoDB는 기본적으로 클러스터형 인덱스를 사용합니다. 클러스터형 인덱스란 테이블 데이터가 인덱스와 함께 정렬된다는 의미입니다. 즉, **기본 키(primary key)**에 따라 데이터가 물리적으로 정렬됩니다.
이 구조로 인해 인덱스가 설정된 특정 열에서 UPDATE가 발생할 때, 다음과 같은 일이 일어납니다:
- 데이터 재정렬: 기본 키가 변경되거나, 인덱스에 영향을 미치는 컬럼이 변경되면 테이블에서 해당 레코드의 위치가 바뀔 수 있습니다. 이는 데이터를 다시 정렬하고 인덱스를 갱신하는 추가적인 작업이 필요하게 만듭니다.
- 인덱스 업데이트: 인덱스는 변경된 데이터를 다시 인덱스에 반영해야 합니다. 즉, 인덱스 트리를 수정하고 재정렬하는 작업이 발생합니다. 따라서, 인덱스가 많은 컬럼에서 UPDATE를 수행할 경우, 이러한 비용이 클 수 있습니다.
2. PostgreSQL에서 인덱스와 UPDATE
PostgreSQL은 기본적으로 비클러스터형 인덱스를 사용합니다. 즉, 인덱스는 테이블의 데이터와는 별도로 관리되며, 데이터는 물리적으로 인덱스 순서와 상관없이 저장됩니다. 이 때문에 MySQL의 클러스터형 인덱스와 달리, 데이터 자체는 물리적으로 재정렬되지 않습니다.
그러나 PostgreSQL에서 UPDATE는 INSERT + DELETE처럼 처리됩니다:
- PostgreSQL은 MVCC(Multiversion Concurrency Control) 방식을 사용하여, UPDATE 시 기존 레코드를 삭제하고 새로운 레코드를 삽입하는 방식으로 처리합니다. 즉, 기존 데이터를 변경하는 대신, 새로운 버전의 데이터를 삽입하는 방식입니다.
- 이때 인덱스는 여전히 갱신되어야 하므로, 인덱스가 걸린 컬럼을 UPDATE할 때도 성능 비용이 발생할 수 있습니다. 그러나 물리적인 재정렬이 없으므로 MySQL의 클러스터형 인덱스에 비해 덜 복잡할 수 있습니다.
3. 성능 차이
- MySQL (InnoDB): 클러스터형 인덱스를 사용하는 MySQL은 인덱스 컬럼에서 UPDATE 작업 시 데이터 재정렬이 필요할 수 있어 성능 비용이 큽니다. 인덱스가 많을수록 업데이트 작업이 느려질 수 있습니다.
- PostgreSQL: PostgreSQL은 비클러스터형 인덱스를 사용하므로 인덱스 컬럼에서 UPDATE 시 데이터 자체는 재정렬되지 않지만, 여전히 인덱스 갱신 작업이 필요합니다. PostgreSQL의 MVCC로 인해 실제로는 레코드를 새로운 버전으로 삽입하는 방식이므로 추가적인 스토리지 비용이 발생할 수 있지만, 클러스터형 인덱스에서 발생하는 물리적 재정렬은 발생하지 않습니다.
4. 결론
PostgreSQL의 비클러스터형 인덱스는 MySQL의 클러스터형 인덱스에 비해 UPDATE 작업에서 데이터 재정렬에 따른 성능 부담이 적습니다. 하지만 여전히 UPDATE 작업 시 인덱스 자체는 갱신해야 하므로, 비용이 전혀 없지는 않습니다. PostgreSQL이 MySQL에 비해 UPDATE 성능에서 유리할 수 있지만, 성능 차이는 인덱스 갯수, 데이터 크기, 트랜잭션 처리 방식 등 여러 요소에 따라 달라질 수 있습니다.
따라서 PostgreSQL에서 UPDATE가 항상 "빠르다"라고 말하기는 어렵지만, 클러스터형 인덱스가 없는 만큼 데이터 재정렬과 관련된 부담은 적다고 볼 수 있습니다.