본문으로 건너뛰기

"PostgreSQL" 태그로 연결된 43개 게시물개의 게시물이 있습니다.

모든 태그 보기

PG19 파티션 MERGE/SPLIT

· 약 5분

PostgreSQL 파티셔닝의 짧은 역사

PostgreSQL의 파티셔닝은 10 버전에서 선언적(declarative) 문법이 들어온 이후 꾸준히 성숙해왔어요. 13에서 UPDATE로 파티션 간 row 이동이 가능해졌고, 14에서 DETACH PARTITION CONCURRENTLY가 추가됐어요. 그리고 PostgreSQL 19에서 마침내 파티션 자체를 병합하고 분할하는 DDL이 들어와요.

ALTER TABLE ... SPLIT PARTITION ...
ALTER TABLE ... MERGE PARTITIONS ...

익숙한 문법입니다. Oracle을 써본 사람이라면 20년 넘게 봐온 구문과 거의 판박입니다. 다만 자세히 보면 문법과 제약에서 결정적인 차이들이 있습니다.

이전까지 PostgreSQL에서는 어떻게 했나

PostgreSQL 18 이하에서 파티션을 병합하려면 이런 절차를 거쳤습니다.

  1. 새로운 합쳐진 파티션 테이블을 생성
  2. 기존 파티션에서 INSERT SELECT로 데이터 이동
  3. 기존 파티션 DETACH
  4. 새 파티션 ATTACH
  5. 기존 파티션 DROP

한 번에 트랜잭션으로 묶기도 까다롭고, 데이터 이동 중 ACCESS EXCLUSIVE LOCK이 걸려 서비스 가용성에도 영향을 줍니다. 분할도 마찬가지로 귀찮았습니다. Oracle에서는 한 줄이면 끝나는 작업이었습니다.

PostgreSQL 19의 새 문법

SPLIT과 MERGE를 각각 예제로 살펴보겠습니다.

SPLIT PARTITION

-- 원본 파티션 테이블
CREATE TABLE sales (
id bigint generated always as identity,
region text not null,
amount numeric
) PARTITION BY LIST (region);

CREATE TABLE sales_all PARTITION OF sales
FOR VALUES IN ('KR', 'JP', 'CN', 'US', 'UK');

-- 하나의 파티션을 셋으로 분할
ALTER TABLE sales SPLIT PARTITION sales_all INTO (
PARTITION sales_asia FOR VALUES IN ('KR', 'JP', 'CN'),
PARTITION sales_us FOR VALUES IN ('US'),
PARTITION sales_uk FOR VALUES IN ('UK')
);

MERGE PARTITIONS

-- 세 파티션을 하나로 합치기
ALTER TABLE sales MERGE PARTITIONS
(sales_asia, sales_us, sales_uk)
INTO sales_all;

문법에서 눈여겨볼 점은 다음과 같습니다.

  • 지원 타입: RANGE, LIST (HASH는 지원하지 않음)
  • RANGE 파티션은 인접(adjacent) 해야 병합 가능
  • LIST는 인접 제약 없음
  • 소스 파티션들은 괄호 (...)로 감싼다
  • 대상 파티션에 PARTITION 키워드를 붙이지 않는다

Oracle의 문법

같은 일을 Oracle에서 하면 이렇게 됩니다. Oracle 쪽은 8i 시절부터 존재해온 문법이라 변주가 많습니다.

SPLIT PARTITION

-- RANGE 파티션 분할 (AT 값 기준)
ALTER TABLE sales SPLIT PARTITION sales_2026 AT (DATE '2026-07-01')
INTO (
PARTITION sales_2026_h1 TABLESPACE ts1,
PARTITION sales_2026_h2 TABLESPACE ts2
);

-- LIST 파티션 분할 (VALUES 기준)
ALTER TABLE sales SPLIT PARTITION sales_all
VALUES ('KR', 'JP', 'CN')
INTO (
PARTITION sales_asia,
PARTITION sales_rest
);

MERGE PARTITIONS

-- 기본 문법
ALTER TABLE sales MERGE PARTITIONS
sales_q1_2026, sales_q2_2026, sales_q3_2026, sales_q4_2026
INTO PARTITION sales_2026;

-- RANGE 전용 TO 단축 문법
ALTER TABLE sales MERGE PARTITIONS
sales_q1_2026 TO sales_q4_2026
INTO PARTITION sales_2026;

나란히 비교

문법 차이

항목PostgreSQL 19Oracle
MERGE 소스 지정MERGE PARTITIONS (p1, p2) 괄호MERGE PARTITIONS p1, p2 나열
MERGE 대상 지정INTO p_newINTO PARTITION p_new
SPLIT 경계 지정FOR VALUES IN (...) / FOR VALUES FROM ... TO ...AT (value) (RANGE) / VALUES (...) (LIST)
RANGE 범위 병합 단축없음 (일일이 나열)p1 TO p4 단축 문법
TABLESPACE 지정각 대상 파티션마다 개별동일

기능/제약 차이

항목PostgreSQL 19Oracle
지원 파티션 타입RANGE, LISTRANGE, LIST, SYSTEM
HASH 파티션지원 안 함지원 안 함
RANGE 인접 조건필요필요
LIST 인접 조건불필요불필요
락 수준ACCESS EXCLUSIVE (전 구간)EXCLUSIVE + ONLINE 옵션 (EE 12.2+)
실행 방식단일 프로세스병렬 실행 가능

실전에서 갈리는 락과 온라인 실행

문법은 거의 맞춰졌습니다. 하지만 운영에서 진짜 갈리는 것은 락과 온라인 실행 여부입니다.

PostgreSQL 19

공식 커밋 메시지와 depesz의 벤치(1천만 행 LIST 파티션 기준)에서 확인된 내용은 다음과 같습니다.

  • 작업 전체 구간에서 ACCESS EXCLUSIVE LOCK 유지
  • 단일 프로세스에서 순차 실행
  • 대규모 파티션에서는 실질적 다운타임이 발생할 수 있음

쓸모 있는 평가는 이렇습니다. "편의성은 크게 좋아졌지만, 온라인성은 Oracle을 따라잡지 못했습니다." 한 줄 SQL로 간단히 표현할 수 있게 된 것만으로도 의미가 크지만, 수백 GB 파티션을 무중단으로 합칠 수 있는 수준은 아닙니다.

Oracle

Oracle Enterprise Edition 12.2부터 ONLINE 키워드로 DML 블로킹 없이 파티션을 합치거나 쪼갤 수 있습니다.

ALTER TABLE sales MERGE PARTITIONS
sales_q1_2026, sales_q2_2026
INTO PARTITION sales_h1_2026
ONLINE;

내부적으로는 shadow 구조를 만들고 점진적으로 데이터를 이관하는 방식이라, 배타 락 보유 시간이 거의 없습니다. Enterprise Edition 라이선스가 전제라는 게 큰 단서지만, 대형 운영 환경에서 체감되는 차이는 큽니다.

어디까지 따라왔고, 어디까지 아직인가

따라잡은 것

  • SPLIT/MERGE DDL 자체의 존재: SQL 한 줄로 끝납니다
  • 지원 파티션 타입 (RANGE, LIST)
  • 인접 조건 정책 (RANGE는 인접 필요, LIST는 무관)
  • 다중 분할(한 파티션 → N개)과 다중 병합(N개 → 하나)

아직 못 따라온 것

  • 온라인(ONLINE) 실행: 대형 파티션은 실질적 다운타임이 남음
  • 병렬 실행: 단일 프로세스로만 처리
  • RANGE 범위 병합 단축 문법(p1 TO p4) 없음

PostgreSQL의 역사적 약점 중 하나가 "큰 파티션 테이블의 유지보수가 DDL 한 줄로 안 끝난다"였습니다. PostgreSQL 19는 그 거리를 눈에 띄게 좁혔습니다. 다만 운영에서 가장 아픈 "락을 오래 붙잡는다"는 문제는 남아 있어서, 대형 테이블은 여전히 DETACH CONCURRENTLY + 수동 작업 전략을 병용해야 할 수 있습니다.

Oracle에서 PostgreSQL로 넘어올 때 "제가 쓰던 그 문법, PostgreSQL에도 있어요?"라는 질문의 목록이 하나씩 채워지고 있어요. 이번은 파티션 병합/분할 차례였어요.


참고

PG19 EXPLAIN RDTSC

· 약 5분

EXPLAIN ANALYZE의 불편한 진실

EXPLAIN ANALYZE는 PostgreSQL에서 쿼리 성능을 분석할 때 가장 먼저 쓰는 도구예요. 실제로 쿼리를 실행하면서 각 노드의 실행 시간, 행 수, 루프 횟수를 보여줘요.

그런데 한 가지 문제가 있습니다. EXPLAIN ANALYZE를 붙이는 것 자체가 쿼리를 느리게 만듭니다.

이건 버그가 아니라 구조적인 문제입니다. 공식 문서에서도 이렇게 경고합니다.

"The measurement overhead added by EXPLAIN ANALYZE can be significant, especially on machines with slow gettimeofday() operating-system calls."

왜 느려지나

EXPLAIN ANALYZE는 실행 계획의 각 노드를 통과할 때마다 시간을 측정합니다. 구체적으로는 InstrStartNode(시작)과 InstrStopNode(종료)에서 시스템 시계를 읽습니다.

핵심은 이 시계를 읽는 함수가 clock_gettime()이라는 것입니다.

쿼리 실행 흐름:

SeqScan (100만 행)
├─ 행 1: clock_gettime() → 처리 → clock_gettime()
├─ 행 2: clock_gettime() → 처리 → clock_gettime()
├─ 행 3: clock_gettime() → 처리 → clock_gettime()
│ ...
└─ 행 1,000,000: clock_gettime() → 처리 → clock_gettime()

→ clock_gettime() 호출 횟수: 200만 번

100만 행을 스캔하면 clock_gettime()200만 번 호출됩니다. 중첩된 노드가 있으면 더 늘어납니다. 각 호출이 약 20ns라고 해도, 200만 번이면 40ms의 순수 오버헤드가 발생합니다.

프로파일링을 해보면 InstrStartNode/InstrStopNode의 실행 시간 대부분이 clock_gettime()에서 소비됩니다. 실제 쿼리 로직이 아니라 시간 측정에 시간을 쓰고 있는 것입니다.

clock_gettime()이 뭔데

clock_gettime()은 Linux에서 고해상도 시간을 가져오는 시스템 콜입니다. 정확하고 안정적이지만, 호출할 때마다 비용이 듭니다.

현대 Linux에서는 VDSO (Virtual Dynamic Shared Object)를 통해 커널 진입 없이 호출할 수 있도록 최적화되어 있습니다. 그래도 호출당 약 18~20ns의 오버헤드가 있습니다. 플랫폼에 따라 20~100ns까지 달라질 수 있습니다.

clock_gettime() 호출 경로:

사용자 공간 → VDSO → TSC 레지스터 읽기 → 보정 → 반환

커널 진입 없이 실행되지만
보정 로직 때문에 여전히 비용 발생

매번 이 경로를 거치는 게 문제입니다. 쿼리 노드 처리 시간이 수십 ns 수준이면, 시간 측정 비용이 실제 처리 비용보다 클 수도 있습니다.

TIMING FALSE라는 우회로

사실 PostgreSQL 9.4부터 이 문제의 우회 방법은 있었습니다.

EXPLAIN (ANALYZE, TIMING FALSE) SELECT * FROM large_table;

TIMING FALSE를 쓰면 시간 측정을 건너뜁니다. 실제 행 수와 루프 횟수만 보여줍니다. 오버헤드가 거의 사라집니다.

하지만 타이밍이 없으면 어느 노드가 병목인지 알 수 없습니다. 그래서 실무에서는 결국 TIMING TRUE(기본값)를 쓰게 됩니다.

pg_test_timing 유틸리티로 현재 시스템의 타이밍 오버헤드를 확인할 수 있습니다.

$ pg_test_timing
Testing timing overhead for 3 seconds.
Per loop time including overhead: 18.80 ns

PostgreSQL 19의 해결책: RDTSC

PostgreSQL 19에서는 x86-64 CPU의 RDTSC (Read Time-Stamp Counter) 명령어를 활용합니다.

RDTSC란

CPU에는 TSC(Time Stamp Counter)라는 카운터가 있습니다. CPU 클럭마다 1씩 증가하는 레지스터입니다. RDTSC 명령어는 이 카운터 값을 직접 읽습니다.

clock_gettime(): 사용자 공간 → VDSO → 보정 로직 → 반환
RDTSC: CPU 레지스터 직접 읽기 → 반환

시스템 콜도, VDSO 경유도, 보정 로직도 없습니다. CPU 명령어 하나로 끝납니다.

성능 비교

pg_test_timing으로 측정한 결과:

클럭 소스평균 루프 시간비교
System clock (기존)18.80 ns기준
RDTSC (PG19)11.69 ns38% 감소
RDTSCP16.94 ns10% 감소

200만 번 호출 기준으로 환산하면:

클럭 소스총 오버헤드
System clock~37.6 ms
RDTSC~23.4 ms
절감량~14.2 ms

단일 쿼리에서 14ms라면 크지 않아 보이지만, 중첩 노드가 있거나 행 수가 더 많으면 오버헤드는 기하급수적으로 늘어납니다.

RDTSC vs RDTSCP

두 명령어의 차이를 알아두면 좋습니다.

RDTSCRDTSCP
속도더 빠름 (11.69 ns)약간 느림 (16.94 ns)
순서 보장비순차 실행 가능순서 보장됨
정밀도약간 낮음높음
용도EXPLAIN ANALYZE (상대적 시간 측정)절대적 시간 측정이 필요한 경우

RDTSC는 CPU의 비순차 실행(out-of-order execution)으로 인해 측정 순서가 살짝 뒤바뀔 수 있습니다. 하지만 EXPLAIN ANALYZE에서는 상대적인 시간 차이만 보면 되므로, 약간의 부정확함은 문제가 되지 않습니다.

PostgreSQL 19는 EXPLAIN ANALYZE에는 빠른 RDTSC를, 높은 정밀도가 필요한 다른 경우에는 RDTSCP를 사용합니다.

timing_clock_source 설정

새로운 timing_clock_source 파라미터로 클럭 소스를 제어할 수 있습니다.

-- 현재 설정 확인
SHOW timing_clock_source;

-- 변경 (postgresql.conf 또는 SET)
SET timing_clock_source = 'rdtsc'; -- 빠름, 약간 낮은 정밀도
SET timing_clock_source = 'rdtscp'; -- 높은 정밀도
SET timing_clock_source = 'system'; -- 기존 clock_gettime()

x86-64 CPU에서 해당 명령어를 지원하면 자동으로 RDTSC를 사용합니다. ARM 등 다른 아키텍처에서는 기존 방식이 유지됩니다.

주의사항

x86-64 전용

이번 최적화는 x86-64 아키텍처 전용입니다. ARM 기반 서버(AWS Graviton 등)에서는 적용되지 않습니다. 향후 ARM용 최적화도 추가될 수 있지만, 초기 릴리즈에는 포함되지 않았습니다.

TSC 신뢰성

모든 x86-64 CPU에서 TSC가 동일하게 동작하지는 않습니다. 오래된 CPU나 가상화 환경에서는 TSC가 불안정할 수 있습니다. PostgreSQL은 TSC 지원 여부를 확인한 후 자동으로 적절한 클럭 소스를 선택합니다.

변화의 체감

일상적인 EXPLAIN ANALYZE 사용에서 이 변화를 극적으로 체감하기는 어려울 수 있습니다. 하지만 대량 행을 처리하는 복잡한 쿼리에서는 측정 오버헤드 감소가 실행 시간 측정의 정확도를 높여준다는 점이 핵심입니다.

역사: 6년간의 논의

이 아이디어가 처음 나온 건 2020년입니다. Andres Freund가 PostgreSQL Hackers 메일링 리스트에 "Reduce timing overhead of EXPLAIN ANALYZE using rdtsc?" 라는 제목으로 제안했습니다.

6년 동안 논의와 구현이 이어진 끝에 PostgreSQL 19에 드디어 포함되었습니다. 아이디어 자체는 단순하지만, TSC 안정성 검증, 다양한 CPU/VM 환경 호환성, 정밀도 트레이드오프 같은 세부 사항을 해결하는 데 시간이 걸렸습니다.

정리

기존 (PG18 이하)PG19
클럭 소스clock_gettime()RDTSC
호출당 비용~18.80 ns~11.69 ns
개선율-38% 감소
대상 아키텍처모든 플랫폼x86-64 (자동 감지)
설정없음timing_clock_source

EXPLAIN ANALYZE를 프로덕션에서 쓰는 건 여전히 주의가 필요해요. 하지만 PostgreSQL 19부터는 측정 때문에 발생하는 노이즈가 줄어들어, 더 정확한 성능 분석이 가능해져요.

참고 자료

PostgreSQL 19 새 기능 총정리

· 약 6분

PostgreSQL 19 개요

PostgreSQL 19는 2026년 9월 출시 예정이에요. 기능 동결(Feature Freeze)은 4월 8일에 완료되었고, 5월에 첫 번째 베타가 나올 예정이에요.

PostgreSQL 18이 비동기 I/O, UUIDv7, 가상 생성 컬럼 같은 굵직한 기능을 가져왔다면, PostgreSQL 19는 기존 기능의 실질적 개선과 성능 최적화에 집중하는 릴리즈입니다. 화려하진 않지만 실무에서 체감할 수 있는 변화가 많습니다.

이 글은 2026년 4월 기준으로 작성되었으며, 정식 출시 전까지 일부 내용이 변경될 수 있습니다.

쿼리 플래너 & 실행

GROUP BY ALL

SELECT department, role, COUNT(*)
FROM employees
GROUP BY ALL;

GROUP BY ALL을 쓰면 집계 함수가 아닌 SELECT 표현식을 자동으로 GROUP BY에 포함합니다. 컬럼 5개를 일일이 나열할 필요가 없어졌습니다.

Eager Aggregation

대용량 테이블을 조인하기 전에 먼저 집계하는 최적화입니다. enable_eager_aggregate 파라미터로 제어합니다.

-- 플래너가 자동으로 orders를 먼저 집계한 후 customers와 조인
SELECT c.name, SUM(o.amount)
FROM customers c JOIN orders o ON c.id = o.customer_id
GROUP BY c.name;

조인 대상 행 수가 줄어들기 때문에 대용량 분석 쿼리에서 성능이 크게 개선될 수 있습니다.

COUNT() 자동 최적화

COUNT(1), COUNT(not_null_col)을 자동으로 COUNT(*)로 변환합니다. 습관적으로 COUNT(1)을 쓰던 사람들에게는 반가운 변화입니다.

병렬 TID Range Scan

TID Range Scan이 병렬 실행을 지원합니다. 대규모 테이블에서 특정 범위의 물리적 행을 빠르게 스캔할 수 있습니다.

Incremental Sort 확장

Append/MergeAppend 노드 내에서도 Incremental Sort가 가능해졌습니다. 파티션 테이블의 정렬 성능이 개선됩니다.

EXPLAIN ANALYZE 타이밍 오버헤드 감소

x86-64 CPU에서 RDTSC 명령어를 활용해 시간 측정 오버헤드를 약 38% 줄였습니다. 이 주제는 별도 포스트에서 상세히 다룹니다.

윈도우 함수 개선

IGNORE NULLS / RESPECT NULLS

lag, lead, first_value, last_value, nth_value에서 NULL 처리 방식을 지정할 수 있습니다.

SELECT
ts,
value,
last_value(value) IGNORE NULLS OVER (ORDER BY ts) AS last_non_null
FROM sensor_data;

시계열 데이터에서 NULL 값을 건너뛰고 마지막 유효 값을 가져오는 패턴이 훨씬 간결해졌습니다. 이전에는 서브쿼리나 래터럴 조인이 필요했습니다.

파티셔닝

MERGE / SPLIT PARTITIONS

-- 파티션 병합
ALTER TABLE bookings MERGE PARTITIONS (p_2024_q1, p_2024_q2) INTO p_2024_h1;

-- 파티션 분할
ALTER TABLE bookings SPLIT PARTITION p_2024 INTO
(PARTITION p_2024_h1 FOR VALUES FROM ('2024-01-01') TO ('2024-07-01'),
PARTITION p_2024_h2 FOR VALUES FROM ('2024-07-01') TO ('2025-01-01'));

파티션을 병합하거나 분할하는 DDL이 추가되었습니다. 기존에는 새 파티션을 만들고 데이터를 이동한 뒤 기존 파티션을 삭제해야 했습니다.

COPY TO with Partitioned Tables

파티션 테이블에서 직접 COPY TO가 가능해졌습니다. 이전에는 각 파티션을 개별적으로 복사해야 했습니다.

논리 복제 (Logical Replication)

WAL 레벨 동적 조정

서버 재시작 없이 WAL 레벨을 변경할 수 있습니다. effective_wal_level 읽기 전용 파라미터로 현재 상태를 확인합니다.

이전에는 wal_level = logical 설정 변경 후 반드시 재시작이 필요했습니다. 운영 중인 시스템에서 논리 복제를 활성화할 때 다운타임을 줄일 수 있습니다.

시퀀스 복제

논리 복제에서 시퀀스 값을 동기화할 수 있습니다.

ALTER SUBSCRIPTION my_sub REFRESH SEQUENCES;

WAIT FOR LSN

레플리카가 특정 LSN까지 동기화될 때까지 대기하는 메커니즘입니다. 읽기 일관성이 필요한 경우에 유용합니다.

동기화 모니터링

pg_replication_slotsslotsync_skip_reason 컬럼이 추가되어 슬롯 동기화 지연 원인을 파악할 수 있습니다.

성능 최적화

jsonb_agg 성능 향상

jsonb_agg 함수의 성능이 50% 이상 개선되었습니다. JSON 집계가 많은 API 백엔드에는 반가운 변화입니다.

LISTEN/NOTIFY 최적화

채널별 해시 테이블 기반으로 처리 방식이 변경되어, 많은 채널을 사용하는 환경에서 성능이 개선됩니다.

ICU 문자 변환 최적화

UTF-8 데이터베이스에서 ICU 문자 변환 함수의 성능이 향상되었습니다.

Buffer Cache 알고리즘 변경

Free buffer list를 Clock-sweep 알고리즘으로 교체했습니다.

Temporary Table 트렁케이션 고속화

임시 테이블 truncation 처리가 빨라졌습니다.

모니터링 & 관찰성

pg_stat_statements 확장

  • Generic/Custom 플랜별 호출 횟수 추적
  • FETCH 명령어 정규화
  • IN 절 파라미터 리스트 정규화

VACUUM / ANALYZE 진행 상황

  • mode, started_by 컬럼 추가로 수동/자동 실행 구분 가능
  • VACUUM VERBOSE에서 메모리 사용량 표시
  • vacuumdb --dry-run 옵션 추가
  • log_autoanalyze_min_duration 신규 파라미터로 ANALYZE 로깅 분리

pg_buffercache 확장

pg_buffercache_os_pages로 OS 페이지 분포를 확인할 수 있습니다.

WAL 모니터링

wal_fpi_bytes로 Full Page Image 바이트를 추적합니다.

멀티트랜잭션 통계

pg_get_multixact_stats() 함수로 멀티트랜잭션 사용 현황을 확인할 수 있습니다.

SQL & 함수

random() 날짜/시간 생성

SELECT random('2024-01-01'::date, '2024-12-31'::date);

지정 범위 내 랜덤 날짜/시간을 생성할 수 있습니다. 테스트 데이터 생성이 간편해졌습니다.

base64url 인코딩

encode/decode 함수에서 URL-safe한 base64url 포맷을 지원합니다.

error_on_null()

NULL 값 검증 함수가 추가되었습니다. NULL이 들어오면 에러를 발생시킵니다.

SRF(Set-Returning Function) 인라인

Set-returning 함수의 인라인 최적화가 지원됩니다.

관리 & 도구

regdatabase 타입

데이터베이스 이름과 OID를 상호 변환하는 새 객체 식별자 타입입니다.

CHECKPOINT 개선

FLUSH_UNLOGGED, MODE 파라미터가 추가되었습니다.

pg_upgrade 대용량 객체 최적화

대용량 객체(Large Object) 마이그레이션이 빨라졌습니다.

psql 개선

  • %S 프롬프트 옵션으로 검색 경로 표시
  • boolean 값 표시 커스터마이징 (\pset display_true)

pgbench

--continue-on-error 옵션으로 에러 발생 시에도 벤치마크를 계속 진행할 수 있습니다.

그래프 쿼리 (SQL/PGQ)

PostgreSQL 19는 SQL:2023 Part 16(SQL/PGQ) 을 코어에 들였습니다. 관계형 테이블 위에 프로퍼티 그래프 뷰를 얹고, GRAPH_TABLEMATCH 구문으로 그래프 패턴 매칭을 표준 SQL 안에서 풉니다. 별도 그래프 DB나 확장 없이 PostgreSQL만으로 일부 그래프 워크로드를 받아낼 수 있게 되었습니다.

첫 구현은 고정 깊이 패턴까지입니다. 가변 길이 경로는 다음 릴리스의 1차 후보입니다. 이 주제는 분량이 커서 별도 포스트에서 상세히 다룹니다.

호환성 주의

standard_conforming_strings 비활성화 불가

이제 standard_conforming_stringsoff로 설정할 수 없습니다. 비표준 문자열 리터럴(\' 등)은 에러를 발생시킵니다. escape_string_warning 파라미터도 제거되었습니다.

기존에 E'...' 없이 역슬래시 이스케이프를 쓰던 레거시 코드가 있다면 확인이 필요합니다.

log_lock_waits 기본값 변경

log_lock_waits가 기본적으로 활성화됩니다. 잠금 대기 로그가 자동으로 남습니다.

마무리

PostgreSQL 19는 눈에 띄는 신기능보다는 기존 기능의 완성도를 높이는 릴리즈입니다.

제가 개인적으로 주목하는 기능은 매일 쓰게 될 편의 기능인 GROUP BY ALL, 분석 쿼리 성능에 직접 영향을 주는 Eager Aggregation, 운영 중 논리 복제 활성화를 편하게 해주는 WAL 레벨 동적 조정이에요. IGNORE NULLS는 시계열 처리를 깔끔하게 해주고, 표준 그래프 쿼리를 코어에 들인 SQL/PGQ도 눈에 들어와요. EXPLAIN ANALYZE RDTSC다음 글에서, SQL/PGQ후속편에서 상세히 다룹니다.

2026년 9월 정식 출시가 기대되고, 5월 베타부터 미리 테스트해볼 수 있어요.

참고 자료