Mengoptimalkan PostgreSQL untuk data sementara

8

Saya memiliki beberapa tabel dengan masing-masing 100-300 kolom tipe integer, yang menyimpan data yang sangat tidak stabil. Kumpulan data dikunci oleh satu atau dua kunci utama, dan ketika refresh terjadi, seluruh dataset dihapus dan data baru dimasukkan dalam satu transaksi. Ukuran dataset biasanya beberapa ratus baris, tetapi bisa sampai beberapa ribu baris dalam kasus yang ekstrim. Refresh terjadi sekali per detik, dan pembaruan dataset untuk kunci yang berbeda biasanya terputus-putus, sehingga menjatuhkan dan membuat ulang tabel tidak layak.

Bagaimana cara saya menyetel Postgres untuk menangani beban seperti itu? Saya dapat menggunakan versi terbaru dan terhebat jika itu membuat perbedaan.

Alex Tokarev
sumber

Jawaban:

7

Bergantung pada berapa banyak set data yang berbeda, satu opsi adalah mempartisi tabel per-dataset.

Ketika dataset diperbarui, BEGINtransaksi baru, TRUNCATEtabel, COPYdata baru ke dalamnya, dan COMMIT. PostgreSQL memiliki pengoptimalan di mana COPYke dalam tabel yang telah TRUNCATEd dalam transaksi yang sama melakukan jauh lebih sedikit I / O jika Anda menggunakan wal_level = minimal(default).

Jika Anda tidak dapat mempartisi dan memotong (katakanlah, jika Anda berhadapan dengan puluhan atau ratusan ribu kumpulan data, di mana hanya akan ada terlalu banyak tabel) Anda akan ingin menghidupkan autovacuum agar berjalan sebanyak yang bisa dilakukan. , pastikan Anda memiliki indeks yang baik pada apa pun yang Anda hapus berdasarkan, dan bersiaplah untuk kinerja yang agak biasa.

Jika Anda tidak memerlukan keamanan kerusakan - Anda tidak keberatan meja Anda kosong setelah sistem crash - Anda juga dapat membuat tabel Anda sebagai UNLOGGED, yang akan menghemat banyak biaya I / O.

Jika Anda tidak keberatan harus mengembalikan seluruh pengaturan dari cadangan setelah sistem crash, Anda dapat melangkah lebih jauh dan juga mengatur fsync=off, yang pada dasarnya mengatakan kepada PostgreSQL "tidak peduli dengan keselamatan kecelakaan, saya memiliki cadangan yang baik dan saya tidak tidak peduli apakah data saya secara permanen dan benar - benar tidak dapat dipulihkan setelah crash, dan saya senang untuk kembali initdbsebelum saya dapat menggunakan database saya lagi ".

Saya menulis lebih banyak tentang ini di utas serupa di Stack Overflow tentang mengoptimalkan PostgreSQL untuk pengujian cepat ; yang menyebutkan host OS tuning, memisahkan WAL ke disk yang berbeda jika Anda tidak menggunakan unloggedtabel, penyesuaian checkpointer, dll.

Ada juga beberapa info dalam dokumen Pg untuk pemuatan data yang cepat dan pengaturan yang tidak tahan lama .

Craig Ringer
sumber
Terima kasih atas tip partisi, saya tidak pernah berpikir untuk menggunakannya dalam kasus ini. Adapun tabel yang belum di-log - apakah maksud Anda bahwa tabel tersebut kosong secara default setelah kerusakan sistem? Tidak ada bedanya, saya hanya ingin tahu.
Alex Tokarev
1
@AlexTokarev Itu benar; setelah PostgreSQL dimatikan dengan tidak bersih (postmaster atau segfaults backend, siklus daya sistem tiba-tiba, backend di- SIGKILLedit, dll) UNLOGGEDtabel apa saja mungkin TRUNCATEd, sehingga kosong pada saat start-up. Mereka tidak terpotong setelah shutdown dan restart bersih, tetapi Anda tidak harus bergantung pada mereka yang tahan lama.
Craig Ringer
Terima kasih untuk penjelasannya. Saya tidak memerlukan keamanan data untuk tabel yang dimaksud, data di dalamnya bersifat sementara dan disegarkan dari sumber setiap detik. Mematikan fsync bukan pilihan, karena ada tabel lain yang lebih tradisional dalam skema yang sama yang perlu aman dan dapat dipulihkan. Memiliki UNLOGGEDopsi per tabel hanya hebat.
Alex Tokarev
Saya melihat dokumen partisi dan sepertinya itu bisa menjadi (hampir) solusi sempurna untuk masalah ini. Namun satu pertanyaan: jika saya akan memiliki tabel induk untuk skema dan tabel anak untuk menyimpan data, saya akan meminta data dari tabel induk, kan? Jika tabel anak untuk rentang itu ada, kueri akan mengembalikannya, jika tidak, itu akan mengembalikan dataset kosong. Dalam hal ini saya bahkan dapat menjatuhkan dan membuat ulang tabel anak untuk setiap kumpulan data baru. Mengingat keadaan, apa yang akan lebih efektif, TRUNCATEatau DROP/CREATE TABLEberurutan?
Alex Tokarev
@AlexTokarev Saya sarankan Anda TRUNCATEsecara pribadi. Churn DDL memiliki biaya sendiri. Karena Anda membuat perubahan dengan frekuensi tinggi, akan sangat penting untuk memastikan bahwa Anda mengaktifkan agresivitas autovacuum pg_catalog.pg_classdan tabel sistem lainnya yang mungkin menggembung di bawah beban kerja itu.
Craig Ringer