PostgreSQL Performance & Query Optimization · Pelajaran

Statistik Multivariat untuk Kolom Berkorelasi

Buat objek CREATE STATISTICS untuk menangkap dependensi yang diasumsikan independen oleh perencana.

Pelajaran 2 dari 413 langkah

Statistik Multivariat untuk Kolom Berkorelasi adalah pelajaran PostgreSQL Performance & Query Optimization gratis di CoddyKit. Ini adalah pelajaran 2 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar PostgreSQL Performance & Query Optimization, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus PostgreSQL Performance & Query Optimization mencakup 4 pelajaran total.

Asumsi Independensi

Ketika PostgreSQL mengestimasi jumlah baris yang akan dikembalikan oleh suatu kueri, PostgreSQL mengandalkan statistik per kolom yang disimpan dalam pg_statistic. Untuk menggabungkan predikat pada beberapa kolom, perencana membuat asumsi penyederhanaan yang penting: kolom-kolom tersebut independen secara statistik.

Dengan asumsi independensi, selektivitas WHERE a = 1 AND b = 2 dihitung sebagai sel(a=1) * sel(b=2). Perkalian tersebut cepat dan benar — tetapi hanya jika kolom-kolom tersebut benar-benar tidak berkaitan.

Dalam skema nyata, kolom sering berkorelasi: sebuah kota menunjukkan kode pos, sebuah produk menunjukkan kategori, dan tanggal pesanan menunjukkan kuartal fiskal. Ketika perencana mengalikan selektivitas untuk kolom yang berkorelasi, estimasinya dapat jatuh jauh di bawah kenyataan.

Dampak Estimasi Buruk

Estimasi jumlah baris yang meleset beberapa orde besarnya dapat mengarahkan perencana ke rencana yang salah:

  • Perkiraan terlalu rendah → perencana memilih loop bersarang dengan harapan 3 baris, tetapi 300.000 baris tiba → loop menjalankan sisi dalamnya ratusan ribu kali.
  • Perkiraan terlalu rendah → perencana memilih pemindaian indeks + pengambilan dari heap, bukan satu pemindaian sekuensial yang seharusnya lebih murah.
  • Urutan gabungan buruk → hasil antara yang besar diwujudkan terlalu awal, sehingga penggunaan memori melonjak dan data meluber ke disk.

Gejala yang terlihat dalam EXPLAIN ANALYZE adalah kesenjangan lebar antara rows= (estimasi) dan actual rows=. Kesenjangan tersebut merupakan tanda bahwa korelasi mungkin menjadi penyebabnya.

EXPLAIN ANALYZE
SELECT * FROM addresses
WHERE city = 'New York'
  AND state = 'NY';

Melihat Kesalahan Estimasi

Perhatikan tabel addresses yang kolom city-nya menentukan state secara fungsional — setiap baris dengan city = 'New York' juga memiliki state = 'NY'. Kedua predikat memilih baris yang sama, sehingga selektivitas gabungannya sama dengan sel(city) saja.

Namun, perencana mengalikannya: sel(city) * sel(state), sehingga menghasilkan estimasi yang dapat 10× atau 100× terlalu kecil. Pada keluaran EXPLAIN ANALYZE di bawah ini, perhatikan kesenjangan antara jumlah baris yang diestimasi dan jumlah baris aktual pada simpul pemindaian.

EXPLAIN ANALYZE
SELECT count(*) FROM addresses
WHERE city = 'New York'
  AND state = 'NY';
-- Seq Scan ... (rows=12 ...) (actual ... rows=8400 ...)
--                    ^estimate           ^reality

Memperkenalkan CREATE STATISTICS

PostgreSQL 10+ memungkinkan Anda mengajarkan hubungan antar kolom kepada perencana melalui objek statistik ekstensi, yang dibuat dengan CREATE STATISTICS.

Objek statistik ekstensi menetapkan sekumpulan kolom (atau ekspresi) pada satu tabel serta satu atau beberapa jenis statistik yang akan dikumpulkan untuk kolom-kolom tersebut. Setelah dibuat dan dianalisis, perencana menggunakan statistik multivariat ini, bukan mengalikan selektivitas per kolom secara membabi buta.

Ketiga jenis tersebut adalah:

  • ndistinct — jumlah kombinasi berbeda dari kolom-kolom yang tercantum.
  • dependencies — tingkat dependensi fungsional antar kolom.
  • mcv — daftar nilai paling umum pada kelompok kolom.
CREATE STATISTICS stat_addr_city_state
    ON city, state
    FROM addresses;

ANALYZE addresses;

Dependensi Fungsional

Jenis dependencies menangkap dependensi fungsional: seberapa kuat nilai suatu kolom menyiratkan nilai kolom lain. PostgreSQL menyimpan tingkat antara 0 dan 1 untuk setiap arah.

Untuk tabel kita, city → state memiliki tingkat mendekati 1.0 (mengetahui kota sepenuhnya menentukan negara bagian), sedangkan state → city jauh lebih rendah (sebuah negara bagian memiliki banyak kota).

Ketika perencana mengevaluasi WHERE city = ? AND state = ? dan menemukan dependensi city → state yang kuat, perencana berhenti mengalikan dan sebagai gantinya mempertahankan selektivitas kolom penentu pada dasarnya.

CREATE STATISTICS stat_addr_deps (dependencies)
    ON city, state
    FROM addresses;

ANALYZE addresses;

Memeriksa Dependensi yang Disimpan

Setelah ANALYZE, nilai yang dihitung berada dalam tampilan katalog pg_stats_ext (bentuk mentah) dan pg_stats_ext_exprs untuk statistik ekspresi. Kolom dependencies menampilkan tingkat untuk setiap arah.

Tingkat pada atau mendekati 1.000000 untuk "1 => 2" (kolom 1 menyiratkan kolom 2) mengonfirmasi dependensi fungsional yang hampir sempurna — tepat pada kasus ketika asumsi independensi merugikan Anda.

SELECT statistics_name,
       attnames,
       dependencies
FROM pg_stats_ext
WHERE statistics_name = 'stat_addr_deps';
-- dependencies: {"1 => 2": 1.000000, "2 => 1": 0.140000}

ndistinct untuk GROUP BY dan Gabungan

Jenis ndistinct mencatat jumlah kombinasi berbeda di seluruh kolom yang tercantum. Tanpanya, perencana mengestimasi kombinasi berbeda sebagai hasil kali jumlah nilai berbeda per kolom, yang dapat sangat berlebihan untuk kolom yang berkorelasi.

Hal ini paling penting untuk GROUP BY a, b, c (mengestimasi jumlah kelompok) dan untuk agregat berkelompok yang menjadi masukan agregat hash. Estimasi kelompok yang salah menyebabkan tabel hash berukuran terlalu kecil dan data meluber ke disk, atau menyebabkan agregat berbasis pengurutan dipilih secara keliru.

CREATE STATISTICS stat_sales_ndist (ndistinct)
    ON region, country, city
    FROM sales;

ANALYZE sales;

EXPLAIN
SELECT region, country, city, count(*)
FROM sales
GROUP BY region, country, city;

MCV untuk Kombinasi yang Menceng

Dependensi fungsional mengasumsikan hubungan yang seragam di seluruh tabel. Namun, terkadang korelasinya spesifik terhadap nilai — kombinasi tertentu sangat umum, sementara kombinasi lainnya tidak pernah muncul. Di situlah jenis MCV (nilai yang paling umum) unggul.

Daftar MCV pada sekelompok kolom menyimpan kombinasi yang benar-benar sering muncul beserta frekuensinya, sehingga perencana dapat memperkirakan predikat seperti WHERE category = 'A' AND status = 'shipped' menggunakan frekuensi nyata yang diamati untuk pasangan tersebut, bukan perkiraan turunan.

MCV adalah jenis yang paling kuat, tetapi juga paling banyak menggunakan penyimpanan; gunakan jenis ini ketika dependensi saja belum memperbaiki perkiraan.

CREATE STATISTICS stat_orders_mcv (mcv)
    ON category, status
    FROM orders;

ANALYZE orders;

Menggabungkan Beberapa Jenis dalam Satu Objek

Anda dapat meminta beberapa jenis dalam satu objek statistik. Jika Anda menghilangkan seluruh daftar jenis, PostgreSQL akan membuat semua jenis yang berlaku untuk kumpulan kolom tersebut.

Pola yang umum dan praktis adalah mencantumkan ndistinct, dependencies, mcv sekaligus untuk sekumpulan kolom yang muncul bersama dalam klausa WHERE dan GROUP BY. Satu kali ANALYZE kemudian mengisi semuanya.

Perhatikan bahwa mcv dan dependencies hanya mendukung jumlah kolom yang terbatas, dan sebaiknya Anda memusatkan objek statistik pada kolom yang memang dikuerikan bersama — bukan setiap pasangan kolom dalam tabel.

CREATE STATISTICS stat_addr_all (ndistinct, dependencies, mcv)
    ON city, state, zip
    FROM addresses;

ANALYZE addresses;

Statistik pada Ekspresi

PostgreSQL 14+ memperluas CREATE STATISTICS agar mendukung ekspresi, bukan hanya kolom biasa. Jika kueri Anda memfilter berdasarkan date_trunc('month', created_at) atau lower(email), biasanya perencana tidak memiliki statistik untuk nilai hasil perhitungan tersebut dan kembali menggunakan perkiraan umum.

Objek statistik dengan satu ekspresi memberikan statistik per ekspresi kepada perencana; objek dengan banyak kolom yang mencampurkan ekspresi dan kolom menangkap korelasi antara nilai hasil perhitungan dan kolom yang tersimpan.

CREATE STATISTICS stat_login_expr
    ON lower(email), date_trunc('day', created_at)
    FROM logins;

ANALYZE logins;

Alur Kerja, Pemeliharaan, dan Pembersihan

Statistik tambahan tidak dibuat secara otomatis — Anda membuatnya dengan sengaja berdasarkan kesalahan perkiraan yang teramati. Alur kerja yang andal:

  • Temukan kueri yang EXPLAIN ANALYZE-nya menunjukkan selisih besar antara perkiraan dan kenyataan pada predikat dengan banyak kolom.
  • Buat objek statistik tepat pada kolom-kolom yang berkorelasi tersebut.
  • Jalankan ANALYZE pada tabel (atau tunggu analisis oleh autovacuum) untuk mengisinya.
  • Jalankan kembali EXPLAIN ANALYZE dan pastikan perkiraan tersebut kini mengikuti kenyataan.

Objek statistik diperbarui setiap kali ANALYZE dijalankan, sehingga setelah dibuat, objek tersebut tetap mutakhir secara otomatis. Hapus objek yang tidak lagi diperlukan dengan DROP STATISTICS agar Anda tidak perlu menanggung biaya ANALYZE-nya.

DROP STATISTICS IF EXISTS stat_addr_deps;

Pemeriksaan Singkat: Memilih Jenis yang Tepat

Anda memiliki kueri SELECT count(*) FROM addresses WHERE city = $1 AND state = $2. EXPLAIN ANALYZE menunjukkan bahwa perencana memperkirakan 15 baris, tetapi kenyataannya ada 9.000 baris yang cocok karena city sepenuhnya menentukan state. Jenis statistik tambahan mana yang paling langsung memperbaiki perkiraan ini?

Ringkasan

Perencana mengasumsikan kolom-kolom tidak saling bergantung dan mengalikan selektivitas tiap kolom — hal ini meremehkan jumlah baris ketika kolom saling berkorelasi, sehingga menghasilkan rencana yang buruk.

  • CREATE STATISTICS mengajarkan perencana tentang hubungan antarkolom.
  • dependencies memperbaiki perkiraan yang terlalu rendah pada filter kesetaraan akibat dependensi fungsional (misalnya city → state).
  • ndistinct memperbaiki perkiraan kombinasi berbeda untuk GROUP BY dan agregat berkelompok.
  • mcv menangkap kombinasi yang miring dan spesifik terhadap nilai untuk mendapatkan selektivitas per pasangan yang paling akurat.
  • Buat statistik pada ekspresi (PG14+), perbarui melalui ANALYZE, verifikasi dengan EXPLAIN ANALYZE, dan periksa hasilnya di pg_stats_ext.

Sasar hanya kolom yang benar-benar dikuerikan bersama, lalu pastikan selisih antara perkiraan dan kenyataan menyusut.

Gratis untuk memulai

Belajar SQL dengan tutor AI — gratis

Tulis dan jalankan kode asli di browser kamu, dapatkan bantuan instan dari tutor AI 24/7, dan lanjutkan di mana kamu tinggalkan di web atau aplikasi.

Kursus
22
Pelajaran
88

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Statistik Multivariat untuk Kolom Berkorelasi” gratis?

Ya — teks lengkap “Statistik Multivariat untuk Kolom Berkorelasi” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus PostgreSQL Performance & Query Optimization, upgrade ke CoddyKit PRO. Kursus PostgreSQL Performance & Query Optimization mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Statistik Multivariat untuk Kolom Berkorelasi”?

Buat objek CREATE STATISTICS untuk menangkap dependensi yang diasumsikan independen oleh perencana. Kamu berlatih PostgreSQL Performance & Query Optimization dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai PostgreSQL Performance & Query Optimization?

Tidak diperlukan pengalaman sebelumnya. PostgreSQL Performance & Query Optimization di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 2 dari 4.

Berapa lama pelajaran “Statistik Multivariat untuk Kolom Berkorelasi” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran PostgreSQL Performance & Query Optimization ini?

Ya. Setiap pelajaran PostgreSQL Performance & Query Optimization menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Cara Perencana Memperkirakan Jumlah Baris
  2. Statistik Multivariat untuk Kolom Berkorelasi
  3. Koreksi MCV dan N-Distinct
  4. Memvalidasi Estimasi terhadap Baris Aktual
← Kembali ke PostgreSQL Performance & Query Optimization