Saya beralih ke PostgreSQL dari SQLite untuk aplikasi Rails yang khas.
Masalahnya adalah bahwa spesifikasi berjalan lambat dengan PG.
Pada SQLite butuh ~ 34 detik, pada PG itu ~ 76 detik yang lebih dari 2x lebih lambat .
Jadi sekarang saya ingin menerapkan beberapa teknik untuk membawa kinerja spesifikasi setara dengan SQLite tanpa modifikasi kode (idealnya hanya dengan mengatur opsi koneksi, yang mungkin tidak mungkin).
Beberapa hal yang jelas dari kepala saya adalah:
- RAM Disk (setup yang baik dengan RSpec pada OSX akan bagus untuk dilihat)
- Tabel tidak terdaftar (dapatkah diterapkan pada seluruh basis data sehingga saya tidak mengubah semua skrip?)
Seperti yang mungkin sudah Anda pahami, saya tidak peduli dengan keandalan dan sisanya (DB hanyalah benda yang bisa dibuang di sini).
Saya perlu mendapatkan hasil maksimal dari PG dan membuatnya secepat mungkin .
Jawaban terbaik idealnya menggambarkan trik untuk melakukan hal itu, pengaturan dan kelemahan dari trik itu.
UPDATE: fsync = off
+ full_page_writes = off
hanya mengurangi waktu hingga ~ 65 detik (~ -16 detik). Awal yang bagus, tetapi jauh dari target 34.
UPDATE 2: Saya mencoba menggunakan RAM disk tetapi kenaikan kinerja berada dalam margin kesalahan. Jadi sepertinya tidak sepadan.
UPDATE 3: * Saya menemukan hambatan terbesar dan sekarang spesifikasi saya berjalan secepat yang SQLite.
Masalahnya adalah pembersihan basis data yang melakukan pemotongan . Rupanya SQLite terlalu cepat di sana.
Untuk "memperbaikinya", saya membuka transaksi sebelum setiap tes dan mengembalikannya di akhir.
Beberapa angka untuk ~ 700 tes.
- Pemotongan: SQLite - 34s, PG - 76s.
- Transaksi: SQLite - 17s, PG - 18s.
Peningkatan kecepatan 2x untuk SQLite. Peningkatan kecepatan 4x untuk PG.
sumber
Jawaban:
Pertama, selalu gunakan versi terbaru dari PostgreSQL. Peningkatan kinerja selalu datang, jadi Anda mungkin membuang-buang waktu jika menyetel versi lama. Sebagai contoh, PostgreSQL 9.2 secara signifikan meningkatkan kecepatan
TRUNCATE
dan tentu saja menambahkan hanya scan indeks. Bahkan rilis kecil harus selalu diikuti; lihat kebijakan versi .Larangan
Apakah tidak menaruh tablespace pada RAMdisk atau penyimpanan non-tahan lama lainnya .
Jika Anda kehilangan tablespace seluruh database mungkin rusak dan sulit digunakan tanpa kerja yang signifikan. Ada sedikit keuntungan untuk ini dibandingkan dengan hanya menggunakan
UNLOGGED
tabel dan memiliki banyak RAM untuk cache.Jika Anda benar-benar menginginkan sistem berbasis ramdisk,
initdb
seluruh cluster baru pada ramdisk denganinitdb
memasukkan instance PostgreSQL baru pada ramdisk, sehingga Anda memiliki instance PostgreSQL sekali pakai.Konfigurasi server PostgreSQL
Saat menguji, Anda dapat mengonfigurasi server Anda untuk pengoperasian yang tidak tahan lama namun lebih cepat .
Ini adalah satu-satunya kegunaan yang dapat diterima untuk
fsync=off
pengaturan di PostgreSQL. Pengaturan ini cukup banyak memberi tahu PostgreSQL untuk tidak repot-repot dengan perintah yang tertulis atau hal-hal buruk lainnya seperti integritas data, perlindungan, dan keamanan kecelakaan, yang memberikan izin untuk benar-benar membuang data Anda jika Anda kehilangan daya atau mengalami gangguan OS.Tidak perlu dikatakan, Anda tidak boleh mengaktifkan
fsync=off
produksi kecuali Anda menggunakan Pg sebagai basis data sementara untuk data yang dapat Anda hasilkan kembali dari tempat lain. Jika dan hanya jika Anda melakukan untuk mematikan fsync juga dapatfull_page_writes
mematikan, karena tidak ada gunanya lagi. Berhati-hatilahfsync=off
danfull_page_writes
terapkan pada level cluster , sehingga memengaruhi semua database dalam instance PostgreSQL Anda.Untuk penggunaan produksi Anda mungkin dapat menggunakan
synchronous_commit=off
dan mengaturcommit_delay
, karena Anda akan mendapatkan banyak manfaat yang sama sepertifsync=off
tanpa risiko korupsi data raksasa. Anda memiliki jendela kecil hilangnya data terbaru jika Anda mengaktifkan async commit - tetapi hanya itu.Jika Anda memiliki opsi untuk sedikit mengubah DDL, Anda juga dapat menggunakan
UNLOGGED
tabel di Pg 9.1+ untuk sepenuhnya menghindari logging WAL dan mendapatkan peningkatan kecepatan nyata dengan biaya tabel yang terhapus jika server crash. Tidak ada opsi konfigurasi untuk membuat semua tabel tidak masuk log, harus disetel selamaCREATE TABLE
. Selain bagus untuk pengujian, ini berguna jika Anda memiliki tabel yang penuh dengan data yang dihasilkan atau tidak penting dalam database yang jika tidak berisi hal-hal yang Anda butuhkan agar aman.Periksa log Anda dan lihat apakah Anda mendapat peringatan tentang terlalu banyak pos pemeriksaan. Jika ya, Anda harus meningkatkan checkpoint_segments Anda . Anda mungkin juga ingin menyetel checkpoint_completion_target Anda untuk memperlancar penulisan.
Tune
shared_buffers
agar sesuai dengan beban kerja Anda. Ini tergantung pada OS, tergantung pada apa lagi yang terjadi dengan mesin Anda, dan memerlukan beberapa trial and error. Standarnya sangat konservatif. Anda mungkin perlu meningkatkan batas memori bersama maksimum OS jika Anda meningkatkanshared_buffers
pada PostgreSQL 9.2 dan di bawahnya; 9.3 dan di atas mengubah cara mereka menggunakan memori bersama untuk menghindarinya.Jika Anda hanya menggunakan beberapa koneksi yang banyak bekerja, tingkatkan
work_mem
untuk memberi mereka lebih banyak RAM untuk bermain bersama dll. Hati-hati karenawork_mem
pengaturan yang terlalu tinggi dapat menyebabkan masalah kehabisan memori karena per-sort tidak per-koneksi sehingga satu kueri dapat memiliki banyak jenis bersarang. Anda hanya benar - benar harus meningkatkanwork_mem
jika Anda dapat melihat jenis tumpah ke diskEXPLAIN
atau masuk denganlog_temp_files
pengaturan (disarankan), tetapi nilai yang lebih tinggi juga dapat membiarkan Pg memilih paket yang lebih cerdas.Seperti yang dikatakan oleh poster lain di sini adalah bijaksana untuk meletakkan xlog dan tabel / indeks utama pada HDD terpisah jika memungkinkan. Partisi yang terpisah tidak ada gunanya, Anda benar-benar menginginkan drive yang terpisah. Pemisahan ini memiliki manfaat yang jauh lebih kecil jika Anda menjalankan
fsync=off
dan hampir tidak ada jika Anda menggunakanUNLOGGED
tabel.Akhirnya, sesuaikan kueri Anda. Pastikan bahwa Anda
random_page_cost
danseq_page_cost
mencerminkan kinerja sistem Anda, pastikan Andaeffective_cache_size
benar, dll. GunakanEXPLAIN (BUFFERS, ANALYZE)
untuk memeriksa setiap rencana kueri, dan nyalakanauto_explain
modul untuk melaporkan semua permintaan yang lambat. Anda sering dapat meningkatkan kinerja permintaan secara dramatis hanya dengan membuat indeks yang sesuai atau mengubah parameter biaya.AFAIK tidak ada cara untuk mengatur seluruh database atau cluster
UNLOGGED
. Sangat menarik untuk bisa melakukannya. Pertimbangkan untuk bertanya pada milis PostgreSQL.Host OS tuning
Ada beberapa penyetelan yang dapat Anda lakukan di level sistem operasi juga. Hal utama yang Anda mungkin ingin lakukan adalah meyakinkan sistem operasi untuk tidak menyiram menulis ke disk secara agresif, karena Anda benar-benar tidak peduli kapan / jika mereka membuatnya ke disk.
Di Linux Anda dapat mengontrol ini dengan memori virtual subsistem 's
dirty_*
pengaturan, sepertidirty_writeback_centisecs
.Satu-satunya masalah dengan menyetel pengaturan penulisan kembali menjadi terlalu kendur adalah bahwa flush oleh beberapa program lain dapat menyebabkan semua buffer yang terkumpul PostgreSQL juga memerah, menyebabkan warung besar sementara semuanya terhenti pada penulisan. Anda mungkin dapat mengatasi ini dengan menjalankan PostgreSQL pada sistem file yang berbeda, tetapi beberapa flushes mungkin tingkat perangkat atau tingkat host-bukan tingkat sistem file, sehingga Anda tidak dapat mengandalkan itu.
Penyesuaian ini benar-benar mengharuskan Anda bermain-main dengan pengaturan untuk melihat mana yang paling cocok untuk beban kerja Anda.
Pada kernel yang lebih baru, Anda mungkin ingin memastikan bahwa
vm.zone_reclaim_mode
diatur ke nol, karena dapat menyebabkan masalah kinerja yang parah dengan sistem NUMA (sebagian besar sistem saat ini) karena interaksi dengan bagaimana PostgreSQL mengelolashared_buffers
.Penyetelan kueri dan beban kerja
Ini adalah hal-hal yang DO memerlukan perubahan kode; mereka mungkin tidak cocok untuk Anda. Beberapa hal yang mungkin bisa Anda terapkan.
Jika Anda tidak mengelompokkan pekerjaan menjadi transaksi yang lebih besar, mulailah. Banyak transaksi kecil mahal, jadi Anda harus mengumpulkan barang kapan pun memungkinkan dan praktis untuk melakukannya. Jika Anda menggunakan komit async, ini kurang penting, tetapi masih sangat disarankan.
Kapan saja memungkinkan gunakan tabel sementara. Mereka tidak menghasilkan lalu lintas WAL, jadi mereka jauh lebih cepat untuk menyisipkan dan memperbarui. Kadang-kadang ada baiknya menyeruput sekelompok data ke tabel temp, memanipulasi sesuka Anda, lalu melakukan itu
INSERT INTO ... SELECT ...
untuk menyalinnya ke tabel final. Perhatikan bahwa tabel sementara adalah per sesi; jika sesi Anda berakhir atau Anda kehilangan koneksi Anda maka tabel temp hilang, dan tidak ada koneksi lain dapat melihat isi dari tabel temp sesi (s).Jika Anda menggunakan PostgreSQL 9.1 atau yang lebih baru, Anda bisa menggunakan
UNLOGGED
tabel untuk data yang bisa Anda hilangkan, seperti status sesi. Ini terlihat di berbagai sesi dan dipertahankan di antara koneksi. Mereka terpotong jika server dimatikan dengan tidak jelas sehingga mereka tidak dapat digunakan untuk apa pun yang tidak dapat Anda buat kembali, tetapi mereka bagus untuk cache, tampilan terwujud, tabel negara, dll.Secara umum, jangan
DELETE FROM blah;
. GunakanTRUNCATE TABLE blah;
sebaliknya; itu jauh lebih cepat ketika Anda membuang semua baris dalam sebuah tabel. Potong banyak tabel dalam satuTRUNCATE
panggilan jika Anda bisa. Ada peringatan jika Anda melakukan banyakTRUNCATES
tabel kecil berulang kali; lihat: Kecepatan pemotongan PostgresqlJika Anda tidak memiliki indeks pada kunci asing,
DELETE
melibatkan kunci primer yang dirujuk oleh kunci asing itu akan sangat lambat. Pastikan untuk membuat indeks seperti itu jika Anda mengharapkanDELETE
dari tabel yang direferensikan. Indeks tidak diperlukan untukTRUNCATE
.Jangan membuat indeks yang tidak Anda butuhkan. Setiap indeks memiliki biaya perawatan. Cobalah untuk menggunakan satu set indeks minimal dan biarkan scan indeks bitmap menggabungkannya daripada mempertahankan terlalu banyak indeks multi-kolom yang besar dan mahal. Di mana indeks diperlukan, cobalah untuk mengisi tabel terlebih dahulu, lalu buat indeks di akhir.
Perangkat keras
Memiliki cukup RAM untuk menampung seluruh basis data adalah kemenangan besar jika Anda dapat mengelolanya.
Jika Anda tidak memiliki cukup RAM, semakin cepat penyimpanan Anda bisa mendapatkan yang lebih baik. Bahkan SSD yang murah membuat perbedaan besar pada karat yang berputar. Jangan percaya SSD murah untuk produksi, mereka sering tidak crashsafe dan mungkin memakan data Anda.
Belajar
Buku Greg Smith, PostgreSQL 9.0 High Performance tetap relevan meskipun merujuk pada versi yang agak lama. Ini harus menjadi referensi yang bermanfaat.
Bergabunglah dengan milis umum PostgreSQL dan ikuti.
Bacaan:
sumber
Gunakan tata letak disk yang berbeda:
postgresql.conf tweak:
sumber
fsync=off
, meletakkan pg_xlog pada disk terpisah tidak banyak membaik lagi.