PostgreSQL 17/18: Yenilikler ve Performans İyileştirmeleri
PostgreSQL dünyadaki en gelişmiş açık kaynaklı ilişkisel veritabanı olmaya devam ediyor ve 17 ve 18 sürümleri birleşiyor
Bu pozisyon, üretim performansını doğrudan etkileyen önemli iyileştirmelerle sağlanmaktadır.
26 Eylül 2024'te yayımlanan PostgreSQL 17, artımlı VACUUM, SQL/JSON'u getiriyor JSON_TABLE()
ve daha akıllı bir planlayıcı. Eylül 2025'te yayımlanan PostgreSQL 18, yerel eşzamansız G/Ç ekliyor,
sanal olarak oluşturulan sütunlar ve OAuth 2.0: modern uygulamalar için nesiller boyu bir sıçrama.
Ne Öğreneceksiniz
- PostgreSQL 17'deki sorguları ve bakımı iyileştiren temel özellikler
- PostgreSQL 18 eşzamansız I/O'nun yoğun iş yükleri üzerindeki etkisi
- Nasıl kullanılır
JSON_TABLE()yarı yapılandırılmış veriler üzerindeki sorguları basitleştirmek için - Gerçek kıyaslamalar: Yükseltme sonrasında performans ne kadar iyileşiyor?
- PostgreSQL 16'dan 17/18'e yükseltme için pratik kılavuz
PostgreSQL 17: En Etkileyici Haberler
Sürüm 17 üç alana odaklanır: bellek ve depolama yönetimi, SQL/JSON ve planlayıcı performansı. Üretimde etkisi en büyük olan yenilikleri görelim.
Artımlı VAKUM
Geleneksel VAKUM tüm tabloyu tarar. PostgreSQL 17 artımlı VACUUM ile, süreç, yapılandırılabilir "parçalar" halinde çalışarak kilit çekişmesini ve en yüksek G/Ç'yi azaltır. Bu, geleneksel VAKUM'un bozulmaya neden olduğu büyük tablolar için çok önemlidir. kullanıcılara görünür.
-- PostgreSQL 17: configurare l'incremental vacuum
ALTER TABLE ordini SET (
vacuum_max_eager_freeze_failure_rate = 0.03
);
-- Monitorare l'attivita del vacuum
SELECT
schemaname,
tablename,
last_vacuum,
last_autovacuum,
n_dead_tup,
n_live_tup,
n_mod_since_analyze
FROM pg_stat_user_tables
WHERE n_dead_tup > 1000
ORDER BY n_dead_tup DESC;
JSON_TABLE() ile SQL/JSON
JSON_TABLE() ve en çok beklenen SQL haberleri: JSON'u kullanmadan ilişkisel satırlara dönüştürün
işlevler jsonb_to_recordset() veya karmaşık ifadeler. SQL/JSON standardıyla uyumlu
ISO/IEC 9075-2:2023.
-- Prima (PostgreSQL 16): approccio con jsonb_to_recordset
SELECT
evento->>'tipo' AS tipo,
evento->>'utente_id' AS utente_id,
(evento->>'timestamp')::timestamptz AS ts
FROM log_eventi,
jsonb_array_elements(payload->'eventi') AS evento;
-- Dopo (PostgreSQL 17): JSON_TABLE() standard ISO
SELECT jt.*
FROM log_eventi,
JSON_TABLE(
payload,
'$.eventi[*]' COLUMNS (
tipo VARCHAR(50) PATH '$.tipo',
utente_id BIGINT PATH '$.utente_id',
ts TIMESTAMPTZ PATH '$.timestamp'
)
) AS jt;
JSON_TABLE() bu sadece daha temiz bir sözdizimi değil: planlayıcı onu daha iyi optimize edebilir,
yanal birleşmelere ve işlevlere dayalı 17 öncesi yaklaşımlara göre daha verimli planlar oluşturmak.
Sorgu Planlayıcı iyileştirmeleri
PostgreSQL 17, aralık taramaları için seçicilik tahmininde önemli iyileştirmeler içerir,
için tahmini maliyette azalma DISTINCT dizinli sütunlarda ve en iyi kullanımda
varlığında B-Tree endekslerinin IS NULL e IS NOT NULL.
-- Verificare miglioramenti al planner con EXPLAIN
EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON)
SELECT DISTINCT categoria_id
FROM prodotti
WHERE prezzo IS NOT NULL
AND disponibile = true;
-- PostgreSQL 17 usa meglio gli indici composti in questi scenari
CREATE INDEX CONCURRENTLY idx_prodotti_cat_prezzo
ON prodotti (categoria_id, prezzo)
WHERE disponibile = true;
PostgreSQL 18: Eşzamansız G/Ç'ye Geçiş
PostgreSQL 18, en köklü mimari değişikliklerden biri olan yerel eşzamansız I/O'yu sunuyor
son yılların. Tarihsel olarak PostgreSQL kullanıldı pread() senkron: her işlem
okuma işlemi tamamlanana kadar engelledi. Asenkron G/Ç ile daha fazla işlem
modern NVMe donanımından daha iyi yararlanılarak okuma aynı anda başlatılabilir.
-- postgresql.conf: nuovi parametri per l'I/O asincrono in PG18
# Abilitare il backend I/O asincrono (default: io_uring su Linux 5.1+)
io_method = io_uring # oppure 'worker' per compatibilita
# Numero massimo di richieste I/O asincrone in volo
io_max_concurrency = 32 # da aumentare per NVMe ad alte IOPS
# Dimensione della coda I/O per worker
io_workers = 4 # worker thread per operazioni I/O
io_uring uyumluluğu
io_uring Linux çekirdeği 5.1+ gerektirir. Daha eski çekirdeklere sahip sistemlerde veya macOS/Windows üzerinde,
PostgreSQL 18 otomatik olarak geri dönüş yapar io_method = workerancak bu iyileşir
geleneksel senkronla karşılaştırıldığında verim.
Sanal Olarak Oluşturulan Sütunlar
PostgreSQL 17'de şunlar vardı: saklandı oluşturulan sütunlar (değer hesaplanır ve diske kaydedilir). PostgreSQL 18 şunları ekler: sanal oluşturulan sütunlar: değer anında hesaplanır disk alanı kaplamadan okuma. Hafif dönüşümler için idealdir.
-- PostgreSQL 18: virtual generated column (non salvata su disco)
CREATE TABLE prodotti (
id BIGSERIAL PRIMARY KEY,
nome TEXT NOT NULL,
prezzo_netto NUMERIC(10,2) NOT NULL,
iva_pct NUMERIC(5,2) NOT NULL DEFAULT 22.0,
-- virtual: calcolata al volo, 0 spazio su disco
prezzo_lordo NUMERIC(10,2) GENERATED ALWAYS AS
(ROUND(prezzo_netto * (1 + iva_pct / 100), 2)) VIRTUAL
);
-- La colonna e disponibile come le altre nelle query
SELECT nome, prezzo_netto, prezzo_lordo
FROM prodotti
WHERE prezzo_lordo BETWEEN 100 AND 500;
OAuth 2.0 Kimlik Doğrulaması
PostgreSQL 18, kimlik doğrulama yöntemi olarak OAuth 2.0'ı yerel olarak destekleyerek ihtiyacı ortadan kaldırır
kurumsal kimlik sağlayıcılarıyla (Azure AD, Okta, Google) entegre edilecek harici proxy'ler veya sarmalayıcılar
Çalışma alanı). Yapılandırma şurada gerçekleşir: pg_hba.conf.
-- pg_hba.conf: autenticazione OAuth 2.0 (PostgreSQL 18)
# TYPE DATABASE USER ADDRESS METHOD OPTIONS
hostssl all app_user all oauth issuer="https://login.microsoftonline.com/tenant-id/v2.0"
scope="postgres"
Gerçek Karşılaştırmalar: Performans Ne Kadar İyileşir?
Resmi PostgreSQL kıyaslamaları ve topluluk testleri önemli gelişmeler gösteriyor gerçek senaryolarda. Bu sonuçlar tipik üretim donanımında elde edildi: 8 çekirdekli CPU, 32 GB RAM, NVMe SSD.
| Senaryo | PostgreSQL 16 | PostgreSQL 17 | PostgreSQL 18 |
|---|---|---|---|
| %30 ölü tuple ile 50GB'lık masada VAKUM | 480'ler | 310'lar (-35%) | 280'ler (-42%) |
| Sıralı tarama 100 milyon satır (NVMe) | 28'ler | 25s (-%11) | 17s (-39%) |
| 1 milyon JSON belgesinde JSON_TABLE() | Yok | 4.2s | 3.1'ler |
| pgbench TPS (ölçek=1000, istemci=50) | 18.400 | 19.100 (+%3,8) | 21.800 (+%18,5) |
Yükseltme Kılavuzu: PostgreSQL 16'dan 17/18'e
PostgreSQL 17/18'e yükseltme şu adresten yapılabilir: pg_upgrade (yerinde yükseltme, daha hızlı)
veya mantıksal çoğaltma yoluyla (sıfır kesinti süresiyle yükseltme). Her iki yaklaşıma da bakalım.
pg_upgrade ile yükseltme (Hızlı Yöntem)
#!/bin/bash
# Upgrade PostgreSQL 16 -> 17 con pg_upgrade
# 1. Installare PostgreSQL 17 (Ubuntu/Debian)
apt install postgresql-17
# 2. Fermare il cluster 16 (se non si usa --link)
systemctl stop postgresql@16-main
# 3. Eseguire pg_upgrade
/usr/lib/postgresql/17/bin/pg_upgrade \
--old-datadir /var/lib/postgresql/16/main \
--new-datadir /var/lib/postgresql/17/main \
--old-bindir /usr/lib/postgresql/16/bin \
--new-bindir /usr/lib/postgresql/17/bin \
--link \ # Hard link ai file dati: molto piu veloce (no copia)
--check # Prima: solo verifica, nessuna modifica
# 4. Se il check passa, eseguire l'upgrade reale (rimuovere --check)
/usr/lib/postgresql/17/bin/pg_upgrade \
--old-datadir /var/lib/postgresql/16/main \
--new-datadir /var/lib/postgresql/17/main \
--old-bindir /usr/lib/postgresql/16/bin \
--new-bindir /usr/lib/postgresql/17/bin \
--link
# 5. Avviare PostgreSQL 17
systemctl start postgresql@17-main
# 6. Eseguire analyze per aggiornare le statistiche
/usr/lib/postgresql/17/bin/vacuumdb --all --analyze-in-stages
Mantıksal Çoğaltma ile Sıfır Kesinti Süresiyle Yükseltme
-- STEP 1: Sul server PostgreSQL 16 (source)
-- Configurare postgresql.conf
-- wal_level = logical (deve essere gia impostato)
-- max_replication_slots = 10
-- Creare la pubblicazione su tutte le tabelle
CREATE PUBLICATION pg17_migration FOR ALL TABLES;
-- STEP 2: Sul server PostgreSQL 17 (target)
-- Creare lo schema identico (migrare DDL)
-- ...
-- Creare la sottoscrizione
CREATE SUBSCRIPTION pg17_sub
CONNECTION 'host=pg16-host port=5432 dbname=mydb user=replicator'
PUBLICATION pg17_migration
WITH (create_slot = true, slot_name = 'pg17_migration_slot');
-- STEP 3: Monitorare la replica lag
SELECT
slot_name,
confirmed_flush_lsn,
pg_current_wal_lsn() - confirmed_flush_lsn AS lag_bytes
FROM pg_replication_slots;
-- STEP 4: Quando lag e vicino a zero, switchare il traffico
-- (aggiornare load balancer o DNS)
-- STEP 5: Cleanup dopo il cutover
DROP SUBSCRIPTION pg17_sub; -- su PG17
-- Sul PG16:
SELECT pg_drop_replication_slot('pg17_migration_slot');
Yükseltmeler için En İyi Uygulamalar
- Her zaman yürüt
pg_upgrade --checkUyumsuzlukları tespit etmek için gerçek yükseltmeden önce - Geçişten önce yükseltmeyi üretim veritabanının bir kopyasında test edin
- İle
--linkyükseltme neredeyse anında gerçekleşir ancak geri alma PG17'nin ilk başlangıcından sonra - Yükseltmeden sonra uzantıları güncelleyin:
ALTER EXTENSION nome UPDATE - Yavaş sorguları yükseltmeden sonraki bir hafta boyunca izleyin: planlayıcı planları değiştirebilir
Geliştiriciler için Haberler: Geliştirilmiş SQL
Performansın yanı sıra PostgreSQL 17 ve 18, SQL'i basitleştirmek için birçok yeni özellik getiriyor günlük gelişim.
GERİ DÖNÜŞ ile BİRLEŞTİRME (PostgreSQL 17)
-- PostgreSQL 17: MERGE con RETURNING per upsert audit
MERGE INTO inventario AS target
USING (VALUES
(1001, 50, 'warehouse-A'),
(1002, 30, 'warehouse-B')
) AS source(prodotto_id, quantita, location)
ON target.prodotto_id = source.prodotto_id
WHEN MATCHED THEN
UPDATE SET
quantita = target.quantita + source.quantita,
ultimo_aggiornamento = NOW()
WHEN NOT MATCHED THEN
INSERT (prodotto_id, quantita, location, creato_il)
VALUES (source.prodotto_id, source.quantita, source.location, NOW())
RETURNING
prodotto_id,
xmax = 0 AS is_insert, -- true se INSERT, false se UPDATE
quantita;
ON_ERROR ile KOPYALA (PostgreSQL 17)
-- PostgreSQL 17: ignorare righe invalide durante COPY
-- Prima: l'intera operazione falliva alla prima riga corrotta
COPY prodotti (id, nome, prezzo)
FROM '/data/import.csv'
WITH (
FORMAT csv,
HEADER true,
ON_ERROR ignore, -- salta le righe con errori
LOG_VERBOSITY verbose -- logga le righe saltate
);
-- Verificare quante righe sono state saltate
SELECT count(*) FROM pg_temp.copy_summary;
PostgreSQL 17/18 için optimum yapılandırma
Her yükseltme, yapılandırmayı gözden geçirmek için bir fırsattır. Bu parametreler özellikle PG17/18 haberleriyle alakalı.
# postgresql.conf ottimizzato per PostgreSQL 18
# (hardware: 8 core, 32GB RAM, NVMe SSD)
# Memoria
shared_buffers = 8GB # 25% della RAM
effective_cache_size = 24GB # stima totale memoria disponibile
work_mem = 64MB # per sort/hash, attenzione a connessioni parallele
maintenance_work_mem = 2GB # per VACUUM, CREATE INDEX
# I/O asincrono (PostgreSQL 18)
io_method = io_uring # Linux 5.1+
io_max_concurrency = 64 # per NVMe ad alte IOPS
effective_io_concurrency = 200 # per bitmap heap scan
# Parallelismo
max_parallel_workers_per_gather = 4
max_parallel_workers = 8
max_parallel_maintenance_workers = 4
# Incremental VACUUM (PostgreSQL 17)
autovacuum_vacuum_cost_delay = 2ms # piu aggressivo (default: 2ms da PG17)
autovacuum_vacuum_cost_limit = 800 # aumentato da 200
# WAL
wal_level = logical # necessario per logical replication
max_wal_size = 4GB
checkpoint_completion_target = 0.9
Yükseltme Sonrası İzleme
Yükseltme sonrasında aşağıdaki göstergeleri en az bir hafta boyunca aktif olarak izleyin.
-- Query per identificare regressioni di performance post-upgrade
-- Richiede pg_stat_statements
SELECT
LEFT(query, 80) AS query_preview,
calls,
ROUND(mean_exec_time::numeric, 2) AS mean_ms,
ROUND(stddev_exec_time::numeric, 2) AS stddev_ms,
ROUND(total_exec_time::numeric, 0) AS total_ms,
rows / calls AS avg_rows
FROM pg_stat_statements
WHERE calls > 100
AND mean_exec_time > 100 -- query lente (>100ms)
ORDER BY mean_exec_time DESC
LIMIT 20;
-- Verificare se il planner cambia i piani rispetto a PG16
-- (abilitare auto_explain per catturare i piani)
LOAD 'auto_explain';
SET auto_explain.log_min_duration = '500ms';
SET auto_explain.log_analyze = true;
SET auto_explain.log_buffers = true;
Sonuçlar
PostgreSQL 17 ve 18, donanımlarından en iyi şekilde yararlanmak isteyenler için zorunlu yükseltmelerdir.
Artımlı VAKUM, büyük masalardaki tarihi sorunlardan birini çözer, JSON_TABLE()
yarı yapılandırılmış veriler üzerindeki sorguları basitleştirir ve PG18'in eşzamansız I/O'su iyileştirmeler sağlar
NVMe ile G/Ç bağlantılı iş yüklerinde %40'a varan verim.
Serideki bir sonraki makale, sorgu planlarının nasıl okunacağını ve optimize edileceğini anlatıyor
EXPLAIN ANALYZE: Üretimdeki yavaş sorguları tanımlamak için en güçlü teknik.
Seri: Veritabanı Mühendisliği ve Optimizasyonu
- Madde 1 (bu): PostgreSQL 17/18 - Yenilikler ve Performans
- Makale 2: ANALİZİ AÇIKLAMA - Sorgu Planlarını Okuyun ve Optimize Edin
- Madde 3: Gelişmiş Endeksleme - Kısmi, Kaplama, BRIN, GIN
- Madde 4: Tablo Bölümleme - Milyarlarca Satırın Yönetilmesi
- Madde 5: Bağlantı Havuzu Oluşturma - PgBouncer ve Pgpool-II







