Ada 2 bagian untuk pertanyaan saya.
- Apakah ada cara untuk menentukan ukuran awal database di PostgreSQL?
- Jika tidak, bagaimana Anda menangani fragmentasi ketika database tumbuh seiring waktu?
Saya baru-baru ini pindah dari MSSQL ke Postgres, dan salah satu hal yang kami lakukan di dunia MSSQL ketika membuat database adalah menentukan ukuran awal dari database dan log transaksi. Ini mengurangi fragmentasi dan peningkatan kinerja, terutama jika ukuran "normal" dari database diketahui sebelumnya.
Kinerja basis data saya menurun seiring bertambahnya ukuran. Misalnya, beban kerja yang saya lakukan biasanya memakan waktu 10 menit. Ketika basis data tumbuh, waktu ini meningkat. Melakukan VACUUM, VACUUM FULL dan VACUUM FULL ANALYZE tampaknya tidak menyelesaikan masalah. Apa yang memecahkan masalah kinerja menghentikan database, de-fragmenting drive dan kemudian melakukan VACUUM FULL ANALYZE membawa kinerja pengujian saya kembali ke 10 menit semula. Ini membuat saya curiga bahwa fragmentasi inilah yang menyebabkan saya sakit.
Saya tidak dapat menemukan referensi untuk memesan tablespace / ruang database di Postgres. Entah saya menggunakan terminologi yang salah dan dengan demikian tidak menemukan apa-apa, atau ada cara yang berbeda untuk mengurangi fragmentasi sistem file di Postgres.
Ada petunjuk?
Solusinya
Jawaban yang diberikan membantu mengonfirmasi apa yang mulai saya curigai. PostgreSQL menyimpan database di banyak file dan inilah yang memungkinkan database untuk tumbuh tanpa khawatir akan fragmentasi. Perilaku default adalah mengemas file-file ini hingga penuh dengan data tabel, yang baik untuk tabel yang jarang berubah tetapi buruk untuk tabel yang sering diperbarui.
PostgreSQL menggunakan MVCC untuk menyediakan akses bersamaan ke data tabel. Di bawah skema ini, setiap pembaruan membuat versi baru dari baris yang telah diperbarui (ini bisa melalui cap waktu atau nomor versi, siapa tahu?). Data lama tidak segera dihapus, tetapi ditandai untuk dihapus. Penghapusan aktual terjadi ketika operasi VACUUM dilakukan.
Bagaimana ini berhubungan dengan faktor pengisian? Faktor pengisian tabel default 100 sepenuhnya mengemas halaman tabel, yang pada gilirannya berarti bahwa tidak ada ruang di dalam halaman tabel untuk menahan baris yang diperbarui, yaitu baris yang diperbarui akan ditempatkan di halaman tabel yang berbeda dari baris asli. Ini buruk untuk kinerja, seperti yang ditunjukkan oleh pengalaman saya. Karena tabel ringkasan saya sering diperbarui (hingga 1500 baris / detik), saya memilih untuk menetapkan faktor pengisian 20, yaitu 20% dari tabel akan untuk data baris yang dimasukkan dan 80% untuk data pembaruan. Meskipun ini mungkin tampak berlebihan, jumlah besar ruang yang disediakan untuk baris yang diperbarui berarti bahwa baris yang diperbarui tetap berada dalam halaman yang sama dengan yang asli dan ada halaman tabel yang tidak penuh pada saat daemon autovacuum berjalan untuk menghapus baris yang usang.
Untuk "memperbaiki" database saya, saya melakukan yang berikut ini.
- Atur faktor isi tabel ringkasan saya ke 20. Anda dapat melakukan ini pada waktu pembuatan dengan mengirimkan parameter ke CREATE TABLE , atau setelah faktanya melalui ALTER TABLE. Saya mengeluarkan perintah plpgsql berikut:
ALTER TABLE "my_summary_table" SET (fillfactor = 20);
- Mengeluarkan VACUUM FULL, karena ini menulis versi yang sama sekali baru dari file tabel dan oleh karena itu menulis file tabel baru dengan faktor isian baru .
Menjalankan kembali pengujian saya, saya tidak melihat penurunan kinerja bahkan ketika database sebesar yang saya butuhkan dengan jutaan baris.
TL; DR - Fragmentasi file bukan penyebabnya, itu adalah fragmentasi ruang tabel. Ini dimitigasi dengan mengubah faktor pengisian tabel agar sesuai dengan kasus penggunaan khusus Anda.