Contents
see List작성일 2026. 04. 04.
PostgreSQL 17이 2024년 9월 정식 출시되면서 JSON 처리, 병렬 쿼리, 논리 복제 등 핵심 영역에서 중요한 개선이 이루어졌다. 이 글에서는 PostgreSQL 17의 주요 신기능을 실제 SQL 예제와 함께 상세히 다룬다.
1. SQL/JSON 표준 함수 강화
PostgreSQL 17에서는 SQL:2023 표준의 JSON 함수들이 대폭 추가되었다. 기존 PostgreSQL 전용 연산자 대신 표준 SQL 문법으로 JSON을 처리할 수 있다.
JSON_TABLE - JSON을 관계형 테이블로 변환
-- 주문 데이터가 JSON으로 저장된 경우
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
data JSONB NOT NULL
);
INSERT INTO orders (data) VALUES ('
{
"orderId": "ORD-001",
"customer": "김개발",
"items": [
{"name": "키보드", "price": 89000, "qty": 1},
{"name": "마우스", "price": 45000, "qty": 2},
{"name": "모니터", "price": 350000, "qty": 1}
],
"shipping": {"method": "express", "cost": 3000}
}');
-- JSON_TABLE로 주문 항목을 행으로 변환
SELECT jt.*
FROM orders,
JSON_TABLE(
data, '$.items[*]'
COLUMNS (
item_name TEXT PATH '$.name',
unit_price INTEGER PATH '$.price',
quantity INTEGER PATH '$.qty'
)
) AS jt;
-- 결과:
-- item_name | unit_price | quantity
-- 키보드 | 89000 | 1
-- 마우스 | 45000 | 2
-- 모니터 | 350000 | 1
JSON_QUERY와 JSON_VALUE
-- JSON_VALUE: 스칼라 값 추출 (타입 캐스팅 포함)
SELECT
JSON_VALUE(data, '$.customer' RETURNING TEXT) AS customer,
JSON_VALUE(data, '$.shipping.cost' RETURNING INTEGER) AS shipping_cost,
JSON_VALUE(data, '$.orderId') AS order_id
FROM orders;
-- JSON_QUERY: JSON 객체/배열 추출
SELECT
JSON_QUERY(data, '$.shipping') AS shipping_info,
JSON_QUERY(data, '$.items' WITH WRAPPER) AS items_array
FROM orders;
-- JSON_EXISTS: 경로 존재 여부 확인
SELECT *
FROM orders
WHERE JSON_EXISTS(data, '$.items[*] ? (@.price > 100000)');
2. 증분 정렬 (Incremental Sort) 개선
이미 부분적으로 정렬된 데이터에 대해 추가 정렬을 효율적으로 수행한다.
-- 복합 인덱스가 일부 컬럼만 커버하는 경우
CREATE INDEX idx_orders_date ON orders_table (order_date);
EXPLAIN ANALYZE
SELECT * FROM orders_table
ORDER BY order_date, amount DESC
LIMIT 100;
-- Incremental Sort 활용으로 전체 정렬 대비 성능 향상
3. 병렬 쿼리 성능 향상
-- PostgreSQL 17에서 UNION ALL의 병렬 처리 지원
EXPLAIN ANALYZE
SELECT product_id, SUM(quantity) as total_qty
FROM (
SELECT product_id, quantity FROM sales_2024
UNION ALL
SELECT product_id, quantity FROM sales_2025
) combined
GROUP BY product_id
ORDER BY total_qty DESC
LIMIT 20;
-- 병렬 설정 조정
SHOW max_parallel_workers_per_gather; -- 기본값: 2
SET max_parallel_workers_per_gather = 4;
-- 병렬 VACUUM도 개선
VACUUM (PARALLEL 4) large_table;
ANALYZE large_table;
4. 논리 복제 (Logical Replication) 강화
-- PostgreSQL 17: 시퀀스 복제 지원
CREATE PUBLICATION my_pub FOR ALL TABLES, ALL SEQUENCES;
-- 구독자 측
CREATE SUBSCRIPTION my_sub
CONNECTION 'host=primary dbname=mydb user=repl'
PUBLICATION my_pub
WITH (
copy_data = true,
origin = 'none',
failover = true -- 17 신기능: 페일오버 지원
);
-- 복제 상태 모니터링
SELECT slot_name, slot_type, active,
pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) as lag
FROM pg_replication_slots;
5. COPY 성능 대폭 향상
-- PostgreSQL 17에서 COPY 성능 최대 2배 향상
COPY products FROM '/data/products.csv'
WITH (
FORMAT csv,
HEADER true,
DELIMITER ',',
NULL 'NULL'
);
-- 데이터 내보내기
COPY (
SELECT u.name, COUNT(o.id) as order_count, SUM(o.amount) as total
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.name
ORDER BY total DESC
) TO '/tmp/user_summary.csv' WITH (FORMAT csv, HEADER true);
6. 쿼리 최적화 실전 팁
-- 커버링 인덱스로 Index Only Scan
CREATE INDEX idx_users_covering
ON users (email) INCLUDE (name, created_at);
-- 부분 인덱스 (Partial Index)
CREATE INDEX idx_orders_pending
ON orders (created_at)
WHERE status = 'pending';
-- 표현식 인덱스
CREATE INDEX idx_users_lower_email
ON users (LOWER(email));
-- BRIN 인덱스 - 시계열 데이터에 최적
CREATE INDEX idx_logs_brin
ON access_logs USING BRIN (created_at)
WITH (pages_per_range = 32);
7. pg_stat_statements 활용
-- 느린 쿼리 TOP 10
SELECT
LEFT(query, 80) AS query_preview,
calls,
ROUND(total_exec_time::numeric, 2) AS total_ms,
ROUND(mean_exec_time::numeric, 2) AS avg_ms,
rows
FROM pg_stat_statements
ORDER BY mean_exec_time DESC
LIMIT 10;
-- 캐시 적중률 확인
SELECT
LEFT(query, 80) AS query_preview,
shared_blks_read + shared_blks_hit AS total_blocks,
ROUND(100.0 * shared_blks_hit /
NULLIF(shared_blks_read + shared_blks_hit, 0), 2) AS cache_hit_pct
FROM pg_stat_statements
ORDER BY shared_blks_read DESC
LIMIT 10;
PostgreSQL 17은 JSON 표준 함수 지원과 논리 복제 강화를 통해 현대적인 애플리케이션 요구사항을 더 잘 충족한다. 특히 JSON_TABLE 함수는 JSON 데이터를 관계형 쿼리로 다루는 큰 진전이다. 업그레이드를 적극 권장한다.
database
| No | 작성일 | Title |
|---|---|---|
| 3348 | 2026. 08. 11. | PostgreSQL 잠금 대기 줄이기: 트랜잭션 범위와 lock_timeout 설정 실전 가이드 |
| 3316 | 2026. 08. 03. | PostgreSQL 백업 복구 실전 가이드: pg_dump·pg_restore로 장애 복구 절차 만들기 |
| 3284 | 2026. 07. 26. | PostgreSQL 인덱스가 있는데도 느린 쿼리 해결하기: EXPLAIN ANALYZE와 복합 인덱스 설계 |
| 3254 | 2026. 07. 18. | PostgreSQL 잠금 대기 진단 가이드: pg_stat_activity로 블로킹 쿼리 찾고 장애 줄이기 |
| 3202 | 2026. 07. 09. | PostgreSQL 백업 복구 검증 가이드: pg_dump와 psql로 실제 복원까지 확인하기 |
| 3170 | 2026. 07. 01. | MySQL 느린 쿼리 원인 찾기: EXPLAIN과 복합 인덱스 점검 가이드 |
| 3116 | 2026. 06. 23. | PostgreSQL 트랜잭션 충돌 줄이기: 잠금 순서와 짧은 재시도로 데드락 대응하기 |
| 3058 | 2026. 06. 15. | PostgreSQL JSONB 조회 튜닝: GIN 인덱스와 생성 컬럼으로 느린 검색 줄이기 |
| 2971 | 2026. 06. 07. | MySQL/MariaDB 복합 인덱스 설계: 느린 목록 조회를 줄이는 WHERE·ORDER BY 점검법 |
| 2914 | 2026. 05. 30. | PostgreSQL Autovacuum 운영 점검: 테이블 팽창과 느린 쿼리를 막는 VACUUM·ANALYZE 실전 가이드 |