[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

PostgreSQL POSITION 함수로 문자열 내 위치 찾기

PostgreSQL에서 문자열 처리 작업을 하다 보면, 특정 단어가 문자열 안에 포함되어 있는지 또는 어느 위치에 있는지를 알아야 할 때가 있습니다. 이럴 때 유용하게 쓸 수 있는 함수가 바로 POSITION() 입니다. 1. POSITION 함수란? POSITION() 함수는 문자열 안에서 부분 문자열(substring)의 첫 번째 위치를 반환합니다. MySQL의 LOCATE(), Oracle의 INSTR()와 비슷한 역할을 합니다. `POSITION(substring IN string)` 리턴값: 부분 문자열이 시작하는 위치 (1부터 시작) 찾지 못하면: 0 반환 2. 기본 예제 SELECT POSITION('abc' IN '123abc456'); -- 4 SELECT POSITION('zzz' IN '123abc456'); -- 0 'abc'는 네 번째 문자에서 시작하므로 4를 반환합니다. 'zzz'는 존재하지 않기 때문에 0이 나옵니다. ...

8월 13, 2025 · Jun Kang

[PostgreSQL] RDS 쿼리 성능 분석 방법 : pg_stat_statements 설치, 고려사항 및 주요 지표

1. RDS에서의 쿼리 성능 분석, pg_stat_statements란? RDS에서는 외부 익스텐션 사용이 제한된다. 쿼리 통계 및 성능에 대한 지표를 알 수 있는 여러 가지 익스텐션이 있지만, 그중 pg_stat_statements가 허용된다. pg_stat_statements의 원리, 사용법, 주요 지표에 대해 알아보자. pg_stat_statements는 실행된 쿼리에 대한 통계를 수집하고 저장한다. 다음은 저장되는 주요 지표들이고, 이를 통해 쿼리 성능을 분석하고 최적화할 수 있다. 쿼리빈도 쿼리 실행시간 쿼리 리소스 사용량 (CPU, 디스크I/O, 버퍼 히트 등) 쿼리 텍스트 저장 2. 설치 설치가 되어있지않다면 익스텐션을 먼저 설치하면 된다. ...

8월 14, 2024 · Jun Kang

[PostgreSQL] 문자열에서 날짜/시간 변환 및 처리 과정

1. 문자열에서 날짜/시간으로의 변환 PostgreSQL의 날짜형태의 칼럼을 조회할 때, 종종 정확한 날짜 형태를 사용하는 것이 아닌, 문자열, 혹은 숫자 형태로 간편하게 조회하는 경우가 있다. 예를 들어 2024/05/02 이후의 값을 조회할 때 다음 두 가지 조회 방법을 사용할 수 있다. date_column > '20240502' date_column > TO_DATE('20240502', 'YYYYMMDD') 예제와 같이 PostgreSQL은 일련의 문자/숫자열을 조건에 맞는 날짜형으로 자동으로 디코딩을 해주는데, 문자열을 인식하는 상세 과정을 순서대로 알아보자. 2. 문자열에서 날짜/시간으로의 디코딩 과정 2-1. 문자열을 토큰으로 분리하고 각 토큰을 시간, 시간대, 또는 숫자로 분류한다. 예제들에서는 정상적으로 날짜 및 시간이 변환되는지 확인하기 위해 강제로 TIMESTAMP 및 DATE로 형 변환을 하였지만, 날짜 형태의 데이터와 문자열 그대로를 비교하여도 날짜 및 시간 비교가 가능하다. ...

5월 2, 2024 · Jun Kang