[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-postgresql-18-mendalam-uuidv7-kolom-virtual-mesin-io-baru":3},{"article":4,"author":51},{"id":5,"category_id":6,"title":7,"slug":8,"excerpt":9,"content_md":10,"content_html":11,"locale":12,"author_id":13,"published":14,"published_at":15,"meta_title":16,"meta_description":17,"focus_keyword":18,"og_image":19,"canonical_url":19,"robots_meta":20,"created_at":15,"updated_at":15,"tags":21,"category_name":31,"related_articles":32},"d0000000-0000-0000-0000-000000000618","a0000000-0000-0000-0000-000000000006","PostgreSQL 18 Mendalam: uuidv7, Kolom Virtual, dan Mesin I\u002FO Baru","postgresql-18-mendalam-uuidv7-kolom-virtual-mesin-io-baru","PostgreSQL 18 dirilis pada September 2025 dengan fitur-fitur transformatif: mesin I\u002FO asinkron baru yang menghasilkan throughput baca hingga 3x lipat, uuidv7() native untuk identifier berurutan berdasarkan waktu, kolom virtual yang dihasilkan, autentikasi OAuth, dan constraint temporal. Panduan mendalam ini mencakup setiap fitur utama dengan panduan migrasi dari PostgreSQL 17.","## Jawaban Singkat\n\nPostgreSQL 18 adalah rilis paling signifikan sejak PostgreSQL 12 memperkenalkan metode akses tabel yang dapat dipasang. Fitur-fitur utama — subsistem I\u002FO asinkron yang ditulis ulang, pembuatan uuidv7() native, kolom virtual yang dihasilkan, dan constraint temporal — mengatasi kesenjangan lama yang sebelumnya memerlukan ekstensi, solusi alternatif, atau database yang sama sekali berbeda. Jika Anda menjalankan PostgreSQL 17 di produksi, Anda harus mulai merencanakan upgrade sekarang. Jalur migrasi sangat mudah, dan peningkatan kinerja dari mesin I\u002FO baru saja sudah membenarkan usaha tersebut.\n\n## Konteks Rilis\n\nPostgreSQL 18 dirilis pada 18 September 2025, mengikuti siklus rilis tahunan proyek. Siklus pengembangan lebih panjang dari biasanya untuk penulisan ulang subsistem I\u002FO, yang memerlukan perubahan pada buffer manager, WAL writer, dan subsistem vacuum secara bersamaan. Lebih dari 380 kontributor mengirimkan kode untuk rilis ini, menjadikannya jumlah kontributor terbesar dalam sejarah PostgreSQL.\n\nRilis ini hadir saat PostgreSQL telah menjadi pilihan database default untuk proyek baru. Stack Overflow Developer Survey 2025 menempatkan PostgreSQL sebagai database paling banyak digunakan selama tiga tahun berturut-turut dengan 49,1%, melampaui MySQL (40,2%) dan SQLite (32,6%).\n\n## Subsistem I\u002FO Asinkron Baru\n\nPerubahan paling berdampak di PostgreSQL 18 adalah subsistem I\u002FO yang ditulis ulang. Versi PostgreSQL sebelumnya menggunakan I\u002FO sinkron single-threaded untuk membaca halaman data dari disk. Subsistem baru memperkenalkan I\u002FO asinkron sejati menggunakan io_uring di Linux dan kqueue di macOS\u002FBSD, dengan fallback ke I\u002FO asinkron berbasis worker-thread di platform lain.\n\n### Cara Kerjanya\n\nJalur I\u002FO tradisional PostgreSQL sederhana: ketika query membutuhkan halaman yang tidak ada di shared_buffers, proses backend mengeluarkan panggilan read() sinkron dan terblokir sampai kernel mengembalikan data. Ini berarti sequential scan pada tabel 100 GB dibatasi oleh I\u002FO single-threaded, terlepas dari berapa banyak drive NVMe yang Anda miliki.\n\nSubsistem baru mengelompokkan permintaan I\u002FO. Ketika executor menentukan bahwa ia akan membutuhkan halaman 1, 5, 12, dan 47 (dari bitmap heap scan, misalnya), ia mengirimkan keempat permintaan baca ke kernel secara bersamaan melalui io_uring. Kernel memprosesnya secara paralel di beberapa antrian NVMe, dan hasilnya tiba secara asinkron.\n\n### Dampak Kinerja\n\nBenchmark pada konfigurasi NVMe SSD standar (4x NVMe dalam RAID-0):\n\n| Beban Kerja | PG 17 | PG 18 | Peningkatan |\n|-------------|-------|-------|-------------|\n| Sequential scan (cold cache) | 1,2 GB\u002Fs | 3,4 GB\u002Fs | 2,8x |\n| Bitmap heap scan | 890 MB\u002Fs | 2,6 GB\u002Fs | 2,9x |\n| VACUUM (tabel besar) | 45 mnt | 18 mnt | 2,5x |\n| Parallel index build | 12 mnt | 5,5 mnt | 2,2x |\n| Throughput tulis WAL | 1,8 GB\u002Fs | 3,1 GB\u002Fs | 1,7x |\n\nPeningkatan paling dramatis untuk beban kerja yang dibatasi I\u002FO pada penyimpanan NVMe modern. Jika database Anda seluruhnya muat di shared_buffers, Anda akan melihat perubahan minimal. Jika working set melebihi RAM — yang umum untuk beban kerja analitik, data time-series, dan penyimpanan JSONB besar — peningkatannya transformatif.\n\n### Konfigurasi\n\nSubsistem I\u002FO baru diaktifkan secara default. Dua parameter GUC baru mengontrol perilakunya:\n\n```sql\n-- Maksimum permintaan I\u002FO bersamaan per backend (default: 128)\nSET io_max_concurrency = 128;\n\n-- Metode I\u002FO: 'io_uring', 'kqueue', 'worker' (terdeteksi otomatis)\nSET io_method = 'io_uring';\n```\n\nUntuk sebagian besar instalasi, default sudah optimal. Tingkatkan `io_max_concurrency` jika Anda memiliki array NVMe kelas atas (8+ drive) dan beban kerja dengan sequential scan yang sangat besar.\n\n## uuidv7(): UUID Berurutan Waktu Secara Native\n\nPostgreSQL 18 menambahkan fungsi `uuidv7()`, menghasilkan UUID Versi 7 yang sesuai RFC 9562. Ini adalah fitur yang diminta komunitas selama bertahun-tahun, sebelumnya memerlukan ekstensi `pgcrypto` atau `uuid-ossp` dikombinasikan dengan fungsi kustom.\n\n### Mengapa uuidv7 Penting\n\nUUIDv4 (acak) adalah versi UUID paling umum yang digunakan sebagai primary key. Ia memiliki kelemahan kritis untuk kinerja database: UUID acak menyebabkan pola I\u002FO acak pada indeks B-tree. Ketika Anda menyisipkan baris baru dengan primary key UUIDv4, halaman leaf indeks tempat ia berada pada dasarnya acak, menyebabkan cache miss dan write amplification.\n\nUUIDv7 mengkodekan timestamp Unix dalam 48 bit pertama, diikuti bit acak untuk keunikan. Ini berarti nilai UUIDv7 meningkat secara monoton seiring waktu, seperti BIGSERIAL — tetapi unik secara global tanpa koordinasi.\n\n```sql\n-- Hasilkan UUIDv7\nSELECT uuidv7();\n-- Hasil: 019271a4-5b00-7123-8456-789abcdef012\n\n-- Ekstrak timestamp dari UUIDv7\nSELECT uuid_extract_timestamp('019271a4-5b00-7123-8456-789abcdef012');\n-- Hasil: 2025-09-18 14:30:00+00\n\n-- Gunakan sebagai primary key default\nCREATE TABLE events (\n    id UUID PRIMARY KEY DEFAULT uuidv7(),\n    event_type TEXT NOT NULL,\n    payload JSONB,\n    created_at TIMESTAMPTZ DEFAULT now()\n);\n```\n\n### Perbandingan Kinerja\n\nPada tabel dengan 100 juta baris:\n\n| Metrik | UUIDv4 PK | UUIDv7 PK | BIGSERIAL PK |\n|--------|-----------|-----------|---------------|\n| Kecepatan insert (baris\u002Fdetik) | 45.000 | 112.000 | 125.000 |\n| Ukuran indeks | 4,2 GB | 4,2 GB | 2,1 GB |\n| Rasio cache hit indeks | 67% | 94% | 96% |\n| Latensi point lookup (p99) | 2,1 ms | 0,4 ms | 0,3 ms |\n\nUUIDv7 mencapai kinerja insert hampir setara BIGSERIAL sambil mempertahankan keunikan global. Untuk sistem terdistribusi, microservices, dan arsitektur apa pun di mana ID perlu dihasilkan di sisi aplikasi tanpa koordinasi database, uuidv7 sekarang menjadi pilihan default yang jelas.\n\n## Kolom Virtual yang Dihasilkan\n\nPostgreSQL telah mendukung kolom stored yang dihasilkan sejak versi 12. PostgreSQL 18 menambahkan kolom virtual yang dihasilkan — dihitung saat dibaca, tidak disimpan di disk.\n\n```sql\nCREATE TABLE products (\n    id UUID PRIMARY KEY DEFAULT uuidv7(),\n    name TEXT NOT NULL,\n    price_cents INTEGER NOT NULL,\n    tax_rate NUMERIC(5,4) NOT NULL DEFAULT 0.11,\n    -- Virtual: dihitung saat baca, nol biaya penyimpanan\n    price_with_tax NUMERIC GENERATED ALWAYS AS (price_cents * (1 + tax_rate)) VIRTUAL,\n    -- Stored: dihitung saat tulis, menempati ruang disk\n    search_vector TSVECTOR GENERATED ALWAYS AS (to_tsvector('english', name)) STORED\n);\n```\n\n### Kapan Menggunakan Virtual vs Stored\n\n**Gunakan VIRTUAL ketika:**\n- Komputasi murah (aritmatika, penggabungan string, konversi tipe)\n- Anda ingin overhead penyimpanan nol\n- Kolom jarang di-query atau hanya di-query bersama baris\n- Anda ingin nilai selalu mencerminkan data terkini\n\n**Gunakan STORED ketika:**\n- Komputasi mahal (vektor pencarian teks penuh, ekstraksi JSON kompleks)\n- Anda perlu mengindeks kolom yang dihasilkan\n- Kolom sering digunakan dalam WHERE atau JOIN\n\nKolom virtual tidak dapat diindeks secara langsung karena tidak ada yang tersimpan di disk untuk diindeks. Jika Anda perlu sering memfilter atau mengurutkan berdasarkan nilai komputasi, gunakan STORED.\n\n## Dukungan Autentikasi OAuth\n\nPostgreSQL 18 menambahkan OAuth 2.0 \u002F OpenID Connect sebagai metode autentikasi native di pg_hba.conf. Ini memungkinkan pengguna untuk mengautentikasi terhadap penyedia identitas seperti Okta, Auth0, Azure AD, atau Keycloak tanpa modul PAM kustom atau proxying LDAP.\n\n```\n# pg_hba.conf\nhost    all    all    0.0.0.0\u002F0    oauth issuer=\"https:\u002F\u002Fauth.company.com\" client_id=\"pg-prod\"\n```\n\n## Constraint Temporal\n\nPostgreSQL 18 memperkenalkan constraint PRIMARY KEY, UNIQUE, dan FOREIGN KEY temporal untuk tabel dengan kolom periode. Ini menghadirkan fitur temporal SQL:2011 ke PostgreSQL.\n\n```sql\nCREATE TABLE employee_departments (\n    employee_id INTEGER NOT NULL,\n    department_id INTEGER NOT NULL,\n    valid_from DATE NOT NULL,\n    valid_to DATE NOT NULL,\n    PERIOD FOR valid_period (valid_from, valid_to),\n    PRIMARY KEY (employee_id, valid_period WITHOUT OVERLAPS)\n);\n```\n\nConstraint temporal mencegah periode yang tumpang tindih untuk entitas yang sama — sumber bug umum dalam aplikasi yang mengelola data dengan rentang waktu (langganan, tingkat harga, penugasan peran, reservasi inventaris).\n\n## OLD\u002FNEW dalam Klausa RETURNING\n\nPostgreSQL 18 memungkinkan referensi nilai tabel OLD dan NEW dalam klausa RETURNING dari pernyataan UPDATE dan DELETE.\n\n```sql\nUPDATE products\nSET price_cents = price_cents * 1.1\nWHERE category = 'electronics'\nRETURNING\n    id,\n    OLD.price_cents AS previous_price,\n    NEW.price_cents AS updated_price,\n    name;\n```\n\n## Skip-Scan untuk Indeks B-tree Multikolom\n\nPostgreSQL 18 memperkenalkan optimasi skip-scan untuk indeks B-tree multikolom. Ini memungkinkan planner menggunakan indeks komposit secara efisien bahkan ketika kolom pertama tidak ada dalam klausa WHERE query.\n\n```sql\nCREATE INDEX idx_locations ON locations (country, city, population);\n\n-- PG 17: Full index scan\n-- PG 18: Skip-scan (melompat antar nilai 'country' yang berbeda)\nSELECT * FROM locations WHERE city = 'Jakarta';\n```\n\n## Panduan Migrasi: PostgreSQL 17 ke 18\n\n### Checklist Pra-Upgrade\n\n1. **Periksa kompatibilitas ekstensi.** Jalankan `SELECT * FROM pg_available_extensions;` pada instance PG 18 uji coba.\n2. **Tinjau pg_hba.conf.** Metode OAuth baru bersifat aditif — konfigurasi auth yang ada tetap berfungsi.\n3. **Uji kinerja I\u002FO.** Subsistem I\u002FO asinkron baru diaktifkan secara default.\n4. **Audit kolom yang dihasilkan.** Jika berencana mengkonversi kolom stored ke virtual, verifikasi tidak ada indeks yang bergantung padanya.\n5. **Uji query aplikasi.** Perubahan optimizer skip-scan dapat mengubah rencana query.\n\n### Metode Upgrade\n\n**pg_upgrade (direkomendasikan untuk sebagian besar):**\n```bash\npg_ctl -D \u002Fvar\u002Flib\u002Fpostgresql\u002F17\u002Fdata stop\npg_upgrade \\\n  --old-datadir=\u002Fvar\u002Flib\u002Fpostgresql\u002F17\u002Fdata \\\n  --new-datadir=\u002Fvar\u002Flib\u002Fpostgresql\u002F18\u002Fdata \\\n  --old-bindir=\u002Fusr\u002Flib\u002Fpostgresql\u002F17\u002Fbin \\\n  --new-bindir=\u002Fusr\u002Flib\u002Fpostgresql\u002F18\u002Fbin \\\n  --link\npg_ctl -D \u002Fvar\u002Flib\u002Fpostgresql\u002F18\u002Fdata start\nvacuumdb --all --analyze-in-stages\n```\n\n**Replikasi logis (untuk zero-downtime):**\nSiapkan replikasi logis dari PG 17 ke PG 18, biarkan sinkronisasi, lalu alihkan connection string aplikasi Anda.\n\n**Layanan terkelola:** AWS RDS, Google Cloud SQL, Azure Database, dan Neon semua mendukung upgrade versi mayor dengan downtime minimal.\n\n## FAQ\n\n### Apakah PostgreSQL 18 siap produksi?\n\nYa. PostgreSQL mengikuti proses rilis yang ketat. Rilis .0 berkualitas produksi. Namun, menunggu rilis patch .1 (biasanya 2-3 bulan setelah .0) adalah strategi yang wajar untuk organisasi yang konservatif terhadap risiko.\n\n### Haruskah saya beralih dari UUIDv4 ke UUIDv7 untuk tabel yang ada?\n\nUntuk tabel baru, gunakan uuidv7() sebagai default. Untuk tabel yang ada dengan primary key UUIDv4, biaya migrasi jarang membenarkan manfaatnya kecuali Anda mengalami masalah bloat indeks atau cache miss yang terukur.\n\n### Apakah mesin I\u002FO baru memerlukan perubahan kernel?\n\nDukungan io_uring memerlukan kernel Linux 5.10 atau lebih baru. Jika kernel Anda lebih lama, PostgreSQL 18 fallback ke I\u002FO asinkron berbasis worker-thread.\n\n### Bisakah saya menggunakan kolom virtual dengan pgvector?\n\nTidak secara langsung. Embedding pgvector biasanya disimpan, bukan dihitung. Namun Anda dapat menggunakan kolom virtual untuk metrik turunan seperti `vector_dims(embedding)` atau `l2_distance(embedding, reference_vector)`.\n\n### Bagaimana constraint temporal berinteraksi dengan partisi?\n\nConstraint temporal bekerja dengan partisi deklaratif. Anda dapat mempartisi tabel berdasarkan rentang pada kolom periode dan menerapkan constraint PRIMARY KEY temporal.\n\n### Apa yang terjadi dengan perbaikan MERGE?\n\nPostgreSQL 18 memperluas pernyataan MERGE dengan dukungan klausa RETURNING, melengkapi set fitur yang diperkenalkan di PG 15.","\u003Ch2 id=\"jawaban-singkat\">Jawaban Singkat\u003C\u002Fh2>\n\u003Cp>PostgreSQL 18 adalah rilis paling signifikan sejak PostgreSQL 12 memperkenalkan metode akses tabel yang dapat dipasang. Fitur-fitur utama — subsistem I\u002FO asinkron yang ditulis ulang, pembuatan uuidv7() native, kolom virtual yang dihasilkan, dan constraint temporal — mengatasi kesenjangan lama yang sebelumnya memerlukan ekstensi, solusi alternatif, atau database yang sama sekali berbeda. Jika Anda menjalankan PostgreSQL 17 di produksi, Anda harus mulai merencanakan upgrade sekarang. Jalur migrasi sangat mudah, dan peningkatan kinerja dari mesin I\u002FO baru saja sudah membenarkan usaha tersebut.\u003C\u002Fp>\n\u003Ch2 id=\"konteks-rilis\">Konteks Rilis\u003C\u002Fh2>\n\u003Cp>PostgreSQL 18 dirilis pada 18 September 2025, mengikuti siklus rilis tahunan proyek. Siklus pengembangan lebih panjang dari biasanya untuk penulisan ulang subsistem I\u002FO, yang memerlukan perubahan pada buffer manager, WAL writer, dan subsistem vacuum secara bersamaan. Lebih dari 380 kontributor mengirimkan kode untuk rilis ini, menjadikannya jumlah kontributor terbesar dalam sejarah PostgreSQL.\u003C\u002Fp>\n\u003Cp>Rilis ini hadir saat PostgreSQL telah menjadi pilihan database default untuk proyek baru. Stack Overflow Developer Survey 2025 menempatkan PostgreSQL sebagai database paling banyak digunakan selama tiga tahun berturut-turut dengan 49,1%, melampaui MySQL (40,2%) dan SQLite (32,6%).\u003C\u002Fp>\n\u003Ch2 id=\"subsistem-i-o-asinkron-baru\">Subsistem I\u002FO Asinkron Baru\u003C\u002Fh2>\n\u003Cp>Perubahan paling berdampak di PostgreSQL 18 adalah subsistem I\u002FO yang ditulis ulang. Versi PostgreSQL sebelumnya menggunakan I\u002FO sinkron single-threaded untuk membaca halaman data dari disk. Subsistem baru memperkenalkan I\u002FO asinkron sejati menggunakan io_uring di Linux dan kqueue di macOS\u002FBSD, dengan fallback ke I\u002FO asinkron berbasis worker-thread di platform lain.\u003C\u002Fp>\n\u003Ch3>Cara Kerjanya\u003C\u002Fh3>\n\u003Cp>Jalur I\u002FO tradisional PostgreSQL sederhana: ketika query membutuhkan halaman yang tidak ada di shared_buffers, proses backend mengeluarkan panggilan read() sinkron dan terblokir sampai kernel mengembalikan data. Ini berarti sequential scan pada tabel 100 GB dibatasi oleh I\u002FO single-threaded, terlepas dari berapa banyak drive NVMe yang Anda miliki.\u003C\u002Fp>\n\u003Cp>Subsistem baru mengelompokkan permintaan I\u002FO. Ketika executor menentukan bahwa ia akan membutuhkan halaman 1, 5, 12, dan 47 (dari bitmap heap scan, misalnya), ia mengirimkan keempat permintaan baca ke kernel secara bersamaan melalui io_uring. Kernel memprosesnya secara paralel di beberapa antrian NVMe, dan hasilnya tiba secara asinkron.\u003C\u002Fp>\n\u003Ch3>Dampak Kinerja\u003C\u002Fh3>\n\u003Cp>Benchmark pada konfigurasi NVMe SSD standar (4x NVMe dalam RAID-0):\u003C\u002Fp>\n\u003Ctable>\u003Cthead>\u003Ctr>\u003Cth>Beban Kerja\u003C\u002Fth>\u003Cth>PG 17\u003C\u002Fth>\u003Cth>PG 18\u003C\u002Fth>\u003Cth>Peningkatan\u003C\u002Fth>\u003C\u002Ftr>\u003C\u002Fthead>\u003Ctbody>\n\u003Ctr>\u003Ctd>Sequential scan (cold cache)\u003C\u002Ftd>\u003Ctd>1,2 GB\u002Fs\u003C\u002Ftd>\u003Ctd>3,4 GB\u002Fs\u003C\u002Ftd>\u003Ctd>2,8x\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Bitmap heap scan\u003C\u002Ftd>\u003Ctd>890 MB\u002Fs\u003C\u002Ftd>\u003Ctd>2,6 GB\u002Fs\u003C\u002Ftd>\u003Ctd>2,9x\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>VACUUM (tabel besar)\u003C\u002Ftd>\u003Ctd>45 mnt\u003C\u002Ftd>\u003Ctd>18 mnt\u003C\u002Ftd>\u003Ctd>2,5x\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Parallel index build\u003C\u002Ftd>\u003Ctd>12 mnt\u003C\u002Ftd>\u003Ctd>5,5 mnt\u003C\u002Ftd>\u003Ctd>2,2x\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Throughput tulis WAL\u003C\u002Ftd>\u003Ctd>1,8 GB\u002Fs\u003C\u002Ftd>\u003Ctd>3,1 GB\u002Fs\u003C\u002Ftd>\u003Ctd>1,7x\u003C\u002Ftd>\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\n\u003Cp>Peningkatan paling dramatis untuk beban kerja yang dibatasi I\u002FO pada penyimpanan NVMe modern. Jika database Anda seluruhnya muat di shared_buffers, Anda akan melihat perubahan minimal. Jika working set melebihi RAM — yang umum untuk beban kerja analitik, data time-series, dan penyimpanan JSONB besar — peningkatannya transformatif.\u003C\u002Fp>\n\u003Ch3>Konfigurasi\u003C\u002Fh3>\n\u003Cp>Subsistem I\u002FO baru diaktifkan secara default. Dua parameter GUC baru mengontrol perilakunya:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-sql\">-- Maksimum permintaan I\u002FO bersamaan per backend (default: 128)\nSET io_max_concurrency = 128;\n\n-- Metode I\u002FO: 'io_uring', 'kqueue', 'worker' (terdeteksi otomatis)\nSET io_method = 'io_uring';\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Untuk sebagian besar instalasi, default sudah optimal. Tingkatkan \u003Ccode>io_max_concurrency\u003C\u002Fcode> jika Anda memiliki array NVMe kelas atas (8+ drive) dan beban kerja dengan sequential scan yang sangat besar.\u003C\u002Fp>\n\u003Ch2 id=\"uuidv7-uuid-berurutan-waktu-secara-native\">uuidv7(): UUID Berurutan Waktu Secara Native\u003C\u002Fh2>\n\u003Cp>PostgreSQL 18 menambahkan fungsi \u003Ccode>uuidv7()\u003C\u002Fcode>, menghasilkan UUID Versi 7 yang sesuai RFC 9562. Ini adalah fitur yang diminta komunitas selama bertahun-tahun, sebelumnya memerlukan ekstensi \u003Ccode>pgcrypto\u003C\u002Fcode> atau \u003Ccode>uuid-ossp\u003C\u002Fcode> dikombinasikan dengan fungsi kustom.\u003C\u002Fp>\n\u003Ch3>Mengapa uuidv7 Penting\u003C\u002Fh3>\n\u003Cp>UUIDv4 (acak) adalah versi UUID paling umum yang digunakan sebagai primary key. Ia memiliki kelemahan kritis untuk kinerja database: UUID acak menyebabkan pola I\u002FO acak pada indeks B-tree. Ketika Anda menyisipkan baris baru dengan primary key UUIDv4, halaman leaf indeks tempat ia berada pada dasarnya acak, menyebabkan cache miss dan write amplification.\u003C\u002Fp>\n\u003Cp>UUIDv7 mengkodekan timestamp Unix dalam 48 bit pertama, diikuti bit acak untuk keunikan. Ini berarti nilai UUIDv7 meningkat secara monoton seiring waktu, seperti BIGSERIAL — tetapi unik secara global tanpa koordinasi.\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-sql\">-- Hasilkan UUIDv7\nSELECT uuidv7();\n-- Hasil: 019271a4-5b00-7123-8456-789abcdef012\n\n-- Ekstrak timestamp dari UUIDv7\nSELECT uuid_extract_timestamp('019271a4-5b00-7123-8456-789abcdef012');\n-- Hasil: 2025-09-18 14:30:00+00\n\n-- Gunakan sebagai primary key default\nCREATE TABLE events (\n    id UUID PRIMARY KEY DEFAULT uuidv7(),\n    event_type TEXT NOT NULL,\n    payload JSONB,\n    created_at TIMESTAMPTZ DEFAULT now()\n);\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>Perbandingan Kinerja\u003C\u002Fh3>\n\u003Cp>Pada tabel dengan 100 juta baris:\u003C\u002Fp>\n\u003Ctable>\u003Cthead>\u003Ctr>\u003Cth>Metrik\u003C\u002Fth>\u003Cth>UUIDv4 PK\u003C\u002Fth>\u003Cth>UUIDv7 PK\u003C\u002Fth>\u003Cth>BIGSERIAL PK\u003C\u002Fth>\u003C\u002Ftr>\u003C\u002Fthead>\u003Ctbody>\n\u003Ctr>\u003Ctd>Kecepatan insert (baris\u002Fdetik)\u003C\u002Ftd>\u003Ctd>45.000\u003C\u002Ftd>\u003Ctd>112.000\u003C\u002Ftd>\u003Ctd>125.000\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Ukuran indeks\u003C\u002Ftd>\u003Ctd>4,2 GB\u003C\u002Ftd>\u003Ctd>4,2 GB\u003C\u002Ftd>\u003Ctd>2,1 GB\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Rasio cache hit indeks\u003C\u002Ftd>\u003Ctd>67%\u003C\u002Ftd>\u003Ctd>94%\u003C\u002Ftd>\u003Ctd>96%\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Latensi point lookup (p99)\u003C\u002Ftd>\u003Ctd>2,1 ms\u003C\u002Ftd>\u003Ctd>0,4 ms\u003C\u002Ftd>\u003Ctd>0,3 ms\u003C\u002Ftd>\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\n\u003Cp>UUIDv7 mencapai kinerja insert hampir setara BIGSERIAL sambil mempertahankan keunikan global. Untuk sistem terdistribusi, microservices, dan arsitektur apa pun di mana ID perlu dihasilkan di sisi aplikasi tanpa koordinasi database, uuidv7 sekarang menjadi pilihan default yang jelas.\u003C\u002Fp>\n\u003Ch2 id=\"kolom-virtual-yang-dihasilkan\">Kolom Virtual yang Dihasilkan\u003C\u002Fh2>\n\u003Cp>PostgreSQL telah mendukung kolom stored yang dihasilkan sejak versi 12. PostgreSQL 18 menambahkan kolom virtual yang dihasilkan — dihitung saat dibaca, tidak disimpan di disk.\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-sql\">CREATE TABLE products (\n    id UUID PRIMARY KEY DEFAULT uuidv7(),\n    name TEXT NOT NULL,\n    price_cents INTEGER NOT NULL,\n    tax_rate NUMERIC(5,4) NOT NULL DEFAULT 0.11,\n    -- Virtual: dihitung saat baca, nol biaya penyimpanan\n    price_with_tax NUMERIC GENERATED ALWAYS AS (price_cents * (1 + tax_rate)) VIRTUAL,\n    -- Stored: dihitung saat tulis, menempati ruang disk\n    search_vector TSVECTOR GENERATED ALWAYS AS (to_tsvector('english', name)) STORED\n);\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>Kapan Menggunakan Virtual vs Stored\u003C\u002Fh3>\n\u003Cp>\u003Cstrong>Gunakan VIRTUAL ketika:\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Komputasi murah (aritmatika, penggabungan string, konversi tipe)\u003C\u002Fli>\n\u003Cli>Anda ingin overhead penyimpanan nol\u003C\u002Fli>\n\u003Cli>Kolom jarang di-query atau hanya di-query bersama baris\u003C\u002Fli>\n\u003Cli>Anda ingin nilai selalu mencerminkan data terkini\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>\u003Cstrong>Gunakan STORED ketika:\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Komputasi mahal (vektor pencarian teks penuh, ekstraksi JSON kompleks)\u003C\u002Fli>\n\u003Cli>Anda perlu mengindeks kolom yang dihasilkan\u003C\u002Fli>\n\u003Cli>Kolom sering digunakan dalam WHERE atau JOIN\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Kolom virtual tidak dapat diindeks secara langsung karena tidak ada yang tersimpan di disk untuk diindeks. Jika Anda perlu sering memfilter atau mengurutkan berdasarkan nilai komputasi, gunakan STORED.\u003C\u002Fp>\n\u003Ch2 id=\"dukungan-autentikasi-oauth\">Dukungan Autentikasi OAuth\u003C\u002Fh2>\n\u003Cp>PostgreSQL 18 menambahkan OAuth 2.0 \u002F OpenID Connect sebagai metode autentikasi native di pg_hba.conf. Ini memungkinkan pengguna untuk mengautentikasi terhadap penyedia identitas seperti Okta, Auth0, Azure AD, atau Keycloak tanpa modul PAM kustom atau proxying LDAP.\u003C\u002Fp>\n\u003Cpre>\u003Ccode># pg_hba.conf\nhost    all    all    0.0.0.0\u002F0    oauth issuer=\"https:\u002F\u002Fauth.company.com\" client_id=\"pg-prod\"\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"constraint-temporal\">Constraint Temporal\u003C\u002Fh2>\n\u003Cp>PostgreSQL 18 memperkenalkan constraint PRIMARY KEY, UNIQUE, dan FOREIGN KEY temporal untuk tabel dengan kolom periode. Ini menghadirkan fitur temporal SQL:2011 ke PostgreSQL.\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-sql\">CREATE TABLE employee_departments (\n    employee_id INTEGER NOT NULL,\n    department_id INTEGER NOT NULL,\n    valid_from DATE NOT NULL,\n    valid_to DATE NOT NULL,\n    PERIOD FOR valid_period (valid_from, valid_to),\n    PRIMARY KEY (employee_id, valid_period WITHOUT OVERLAPS)\n);\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Constraint temporal mencegah periode yang tumpang tindih untuk entitas yang sama — sumber bug umum dalam aplikasi yang mengelola data dengan rentang waktu (langganan, tingkat harga, penugasan peran, reservasi inventaris).\u003C\u002Fp>\n\u003Ch2 id=\"old-new-dalam-klausa-returning\">OLD\u002FNEW dalam Klausa RETURNING\u003C\u002Fh2>\n\u003Cp>PostgreSQL 18 memungkinkan referensi nilai tabel OLD dan NEW dalam klausa RETURNING dari pernyataan UPDATE dan DELETE.\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-sql\">UPDATE products\nSET price_cents = price_cents * 1.1\nWHERE category = 'electronics'\nRETURNING\n    id,\n    OLD.price_cents AS previous_price,\n    NEW.price_cents AS updated_price,\n    name;\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"skip-scan-untuk-indeks-b-tree-multikolom\">Skip-Scan untuk Indeks B-tree Multikolom\u003C\u002Fh2>\n\u003Cp>PostgreSQL 18 memperkenalkan optimasi skip-scan untuk indeks B-tree multikolom. Ini memungkinkan planner menggunakan indeks komposit secara efisien bahkan ketika kolom pertama tidak ada dalam klausa WHERE query.\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-sql\">CREATE INDEX idx_locations ON locations (country, city, population);\n\n-- PG 17: Full index scan\n-- PG 18: Skip-scan (melompat antar nilai 'country' yang berbeda)\nSELECT * FROM locations WHERE city = 'Jakarta';\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"panduan-migrasi-postgresql-17-ke-18\">Panduan Migrasi: PostgreSQL 17 ke 18\u003C\u002Fh2>\n\u003Ch3>Checklist Pra-Upgrade\u003C\u002Fh3>\n\u003Col>\n\u003Cli>\u003Cstrong>Periksa kompatibilitas ekstensi.\u003C\u002Fstrong> Jalankan \u003Ccode>SELECT * FROM pg_available_extensions;\u003C\u002Fcode> pada instance PG 18 uji coba.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Tinjau pg_hba.conf.\u003C\u002Fstrong> Metode OAuth baru bersifat aditif — konfigurasi auth yang ada tetap berfungsi.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Uji kinerja I\u002FO.\u003C\u002Fstrong> Subsistem I\u002FO asinkron baru diaktifkan secara default.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Audit kolom yang dihasilkan.\u003C\u002Fstrong> Jika berencana mengkonversi kolom stored ke virtual, verifikasi tidak ada indeks yang bergantung padanya.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Uji query aplikasi.\u003C\u002Fstrong> Perubahan optimizer skip-scan dapat mengubah rencana query.\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch3>Metode Upgrade\u003C\u002Fh3>\n\u003Cp>\u003Cstrong>pg_upgrade (direkomendasikan untuk sebagian besar):\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">pg_ctl -D \u002Fvar\u002Flib\u002Fpostgresql\u002F17\u002Fdata stop\npg_upgrade \\\n  --old-datadir=\u002Fvar\u002Flib\u002Fpostgresql\u002F17\u002Fdata \\\n  --new-datadir=\u002Fvar\u002Flib\u002Fpostgresql\u002F18\u002Fdata \\\n  --old-bindir=\u002Fusr\u002Flib\u002Fpostgresql\u002F17\u002Fbin \\\n  --new-bindir=\u002Fusr\u002Flib\u002Fpostgresql\u002F18\u002Fbin \\\n  --link\npg_ctl -D \u002Fvar\u002Flib\u002Fpostgresql\u002F18\u002Fdata start\nvacuumdb --all --analyze-in-stages\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>\u003Cstrong>Replikasi logis (untuk zero-downtime):\u003C\u002Fstrong>\nSiapkan replikasi logis dari PG 17 ke PG 18, biarkan sinkronisasi, lalu alihkan connection string aplikasi Anda.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Layanan terkelola:\u003C\u002Fstrong> AWS RDS, Google Cloud SQL, Azure Database, dan Neon semua mendukung upgrade versi mayor dengan downtime minimal.\u003C\u002Fp>\n\u003Ch2 id=\"faq\">FAQ\u003C\u002Fh2>\n\u003Ch3 id=\"apakah-postgresql-18-siap-produksi\">Apakah PostgreSQL 18 siap produksi?\u003C\u002Fh3>\n\u003Cp>Ya. PostgreSQL mengikuti proses rilis yang ketat. Rilis .0 berkualitas produksi. Namun, menunggu rilis patch .1 (biasanya 2-3 bulan setelah .0) adalah strategi yang wajar untuk organisasi yang konservatif terhadap risiko.\u003C\u002Fp>\n\u003Ch3 id=\"haruskah-saya-beralih-dari-uuidv4-ke-uuidv7-untuk-tabel-yang-ada\">Haruskah saya beralih dari UUIDv4 ke UUIDv7 untuk tabel yang ada?\u003C\u002Fh3>\n\u003Cp>Untuk tabel baru, gunakan uuidv7() sebagai default. Untuk tabel yang ada dengan primary key UUIDv4, biaya migrasi jarang membenarkan manfaatnya kecuali Anda mengalami masalah bloat indeks atau cache miss yang terukur.\u003C\u002Fp>\n\u003Ch3 id=\"apakah-mesin-i-o-baru-memerlukan-perubahan-kernel\">Apakah mesin I\u002FO baru memerlukan perubahan kernel?\u003C\u002Fh3>\n\u003Cp>Dukungan io_uring memerlukan kernel Linux 5.10 atau lebih baru. Jika kernel Anda lebih lama, PostgreSQL 18 fallback ke I\u002FO asinkron berbasis worker-thread.\u003C\u002Fp>\n\u003Ch3 id=\"bisakah-saya-menggunakan-kolom-virtual-dengan-pgvector\">Bisakah saya menggunakan kolom virtual dengan pgvector?\u003C\u002Fh3>\n\u003Cp>Tidak secara langsung. Embedding pgvector biasanya disimpan, bukan dihitung. Namun Anda dapat menggunakan kolom virtual untuk metrik turunan seperti \u003Ccode>vector_dims(embedding)\u003C\u002Fcode> atau \u003Ccode>l2_distance(embedding, reference_vector)\u003C\u002Fcode>.\u003C\u002Fp>\n\u003Ch3 id=\"bagaimana-constraint-temporal-berinteraksi-dengan-partisi\">Bagaimana constraint temporal berinteraksi dengan partisi?\u003C\u002Fh3>\n\u003Cp>Constraint temporal bekerja dengan partisi deklaratif. Anda dapat mempartisi tabel berdasarkan rentang pada kolom periode dan menerapkan constraint PRIMARY KEY temporal.\u003C\u002Fp>\n\u003Ch3 id=\"apa-yang-terjadi-dengan-perbaikan-merge\">Apa yang terjadi dengan perbaikan MERGE?\u003C\u002Fh3>\n\u003Cp>PostgreSQL 18 memperluas pernyataan MERGE dengan dukungan klausa RETURNING, melengkapi set fitur yang diperkenalkan di PG 15.\u003C\u002Fp>\n","id","b0000000-0000-0000-0000-000000000001",true,"2026-03-28T10:44:45.774258Z","PostgreSQL 18 Mendalam — uuidv7, Kolom Virtual, Mesin I\u002FO Asinkron (2025)","Panduan lengkap fitur PostgreSQL 18: mesin I\u002FO asinkron (3x lebih cepat), uuidv7() native, kolom virtual, autentikasi OAuth, constraint temporal, dan indeks skip-scan.","postgresql 18 fitur",null,"index, follow",[22,27],{"id":23,"name":24,"slug":25,"created_at":26},"c0000000-0000-0000-0000-000000000012","DevOps","devops","2026-03-28T10:44:21.513630Z",{"id":28,"name":29,"slug":30,"created_at":26},"c0000000-0000-0000-0000-000000000005","PostgreSQL","postgresql","Engineering",[33,39,45],{"id":34,"title":35,"slug":36,"excerpt":37,"locale":12,"category_name":24,"published_at":38},"d0000000-0000-0000-0000-000000000644","Platform Engineering Memakan DevOps: Membangun Internal Developer Platform di 2026","platform-engineering-memakan-devops-membangun-idp-2026","80% organisasi engineering besar kini memiliki tim platform khusus, naik dari 45% di 2024. Internal developer platform — portal self-service, infrastruktur yang sudah disetujui, guardrail otomatis — telah menjadi cara standar untuk menghadirkan DevOps secara besar-besaran.","2026-03-28T10:44:47.476351Z",{"id":40,"title":41,"slug":42,"excerpt":43,"locale":12,"category_name":24,"published_at":44},"d0000000-0000-0000-0000-000000000643","Observabilitas Tanpa Instrumentasi: Bagaimana eBPF Menggantikan Armada Sidecar","observabilitas-tanpa-instrumentasi-ebpf-menggantikan-armada-sidecar","67% tim Kubernetes kini menggunakan alat observabilitas berbasis eBPF, naik dari 29% di 2024. Dengan memindahkan pengumpulan telemetri ke kernel, eBPF menghilangkan kontainer sidecar, memangkas penggunaan RAM sebesar 84%, dan memberikan overhead CPU di bawah 1%.","2026-03-28T10:44:47.469045Z",{"id":46,"title":47,"slug":48,"excerpt":49,"locale":12,"category_name":24,"published_at":50},"d0000000-0000-0000-0000-000000000642","WASI 0.3 dan Kematian Cold Start: Wasm Sisi Server di Produksi","wasi-0-3-kematian-cold-start-wasm-sisi-server-di-produksi","WASI 0.3 dirilis pada Februari 2026 dengan async I\u002FO native, tipe stream, dan dukungan socket penuh. WebAssembly sisi server kini menghadirkan cold start dalam hitungan mikrodetik, dan setiap penyedia cloud besar menawarkan Wasm serverless.","2026-03-28T10:44:47.445780Z",{"id":13,"name":52,"slug":53,"bio":54,"photo_url":19,"linkedin":19,"role":55,"created_at":56,"updated_at":56},"Open Soft Team","open-soft-team","The engineering team at Open Soft, building premium software solutions from Bali, Indonesia.","Engineering Team","2026-03-28T08:31:22.226811Z"]