[PostgreSQL] HOT update와 fillfactor — 죽은 튜플을 덜 만드는 쪽

앞선 세 편은 이미 생긴 죽은 튜플을 어떻게 치울 것인가에 대한 이야기였다. 이번 편은 반대쪽이다. 애초에 덜 만드는 방법. UPDATE가 인덱스까지 건드리는 문제 PostgreSQL에서 UPDATE는 새 버전을 쓰는 일이라고 1편에서 정리했다. 그런데 여기 딸려오는 비용이 하나 더 있다. 새 버전이 생기면 그 위치를 가리키도록 인덱스도 갱신해야 한다. 인덱스가 다섯 개인 테이블에서 한 행을 UPDATE하면, 힙에 새 버전 하나가 생기고 인덱스 다섯 곳에 엔트리가 추가된다. 그래서 갱신이 잦은 테이블은 힙보다 인덱스가 먼저 부푸는 경우가 많다. 그리고 인덱스 팽창은 조회 성능에 직접 영향을 준다. ...

9월 12, 2026 · Jun Kang

[PostgreSQL] VACUUM은 도는데 죽은 튜플이 안 줄어들 때

앞선 두 편에서 VACUUM이 공간을 반환하지 않는다는 것과 autovacuum 발동 조건을 다뤘다. 이번 편은 성격이 다르다. 설정을 아무리 만져도 해결되지 않는 경우가 있다. autovacuum은 정상적으로 돌고, 실행 기록도 계속 갱신되는데, 죽은 튜플만 계속 늘어난다. 이건 VACUUM이 게을러서가 아니라 지울 권한이 없어서다. 정리 기준선 VACUUM은 아무 죽은 튜플이나 지우지 않는다. 지워도 되는지 판단하는 기준선이 있다. 기준은 단순하다. 지금 실행 중이거나 앞으로 시작할 어떤 트랜잭션도 이 튜플을 볼 수 없는가. 하나라도 볼 가능성이 있으면 못 지운다. 지웠다가는 그 트랜잭션이 읽어야 할 데이터가 사라진다. ...

9월 11, 2026 · Jun Kang

[PostgreSQL] autovacuum이 큰 테이블에서 안 도는 이유

지난 편에서 죽은 튜플 비율이 계속 올라가고 있다면 설정을 봐야 한다고 썼다. 그 설정 이야기다. 결론부터 말하면, autovacuum의 기본값은 작은 테이블에 맞춰져 있다. 테이블이 커질수록 늦게 돌고, 늦게 도는 만큼 한 번에 할 일이 많아진다. 발동 조건 공식 autovacuum은 테이블마다 임계값을 계산해서, 죽은 튜플 수가 그 값을 넘으면 대상으로 잡는다. 발동 임계값 = autovacuum_vacuum_threshold + autovacuum_vacuum_scale_factor × 테이블 행 수 기본값은 이렇다. 파라미터 기본값 autovacuum_vacuum_threshold 50 autovacuum_vacuum_scale_factor 0.2 (20%) 지배적인 건 뒤쪽 항이다. 행 수에 곱해지기 때문이다. ...

9월 10, 2026 · Jun Kang

[PostgreSQL] VACUUM을 돌렸는데 디스크가 안 줄어드는 이유

VACUUM을 돌렸는데 디스크가 그대로라는 이야기를 종종 듣는다. 정상 동작이다. VACUUM은 공간을 운영체제에 돌려주는 명령이 아니다. VACUUM이 실제로 무엇을 하는지, bloat가 왜 쌓이고 어떻게 재는지까지 정리한다. 죽은 튜플은 어떻게 생기는가 PostgreSQL은 MVCC를 쓰기 때문에 UPDATE가 제자리 수정이 아니다. 기존 행을 고치는 게 아니라 새 버전을 하나 더 쓰고, 예전 버전에 “이 시점 이후로는 무효"라는 표시를 남긴다. DELETE도 마찬가지로 즉시 지우지 않고 무효 표시만 한다. 예전 버전을 바로 못 지우는 이유는 아직 그걸 봐야 하는 트랜잭션이 있을 수 있어서다. 먼저 시작된 트랜잭션에게는 여전히 그 버전이 유효한 데이터다. ...

9월 7, 2026 · Jun Kang

[PostgreSQL] 트랜잭션 ID는 42억 개인데 왜 20억마다 freeze가 도는가

시작은 사소한 의문이었다 PostgreSQL의 트랜잭션 ID(XID)는 32비트다. 그러면 2^32, 약 42억 9천만 개를 쓸 수 있다. 그런데 운영 문서를 읽다 보면 기준선이 자꾸 20억 근처에서 잡힌다. autovacuum_freeze_max_age의 상한도 20억이고, wraparound 경고도 20억 언저리에서 나온다. 공간은 42억인데 왜 절반만 쓰는 걸까. “안전 마진이겠지” 하고 넘어갔다가, 마진치고는 너무 정확히 절반이라는 게 계속 걸렸다. 그래서 물어봤고, 답을 듣고 나니 이건 마진이 아니라 구조적으로 그 이상 쓸 수 없는 값이었다. 순환 카운터에는 “절대적인 전후"가 없다 핵심은 XID가 단조 증가하는 값이 아니라 순환 카운터(circular counter) 라는 데 있다. 42억까지 올라가면 다시 0부터 시작한다. ...

7월 14, 2026 · Jun Kang