PostgreSQL: Memaksa data ke dalam memori

32

Apakah ada cara sistematis untuk memaksa PostgreSQL memuat tabel tertentu ke dalam memori, atau setidaknya membacanya dari disk sehingga akan di-cache oleh sistem?

Adam Matan
sumber

Jawaban:

25

Anda mungkin diinterupsi dalam salah satu topik milis , dijawab oleh Tom Lane (core dev):

[..] Tapi pendapat saya adalah bahwa orang yang berpikir mereka lebih pintar daripada algoritma caching LRU biasanya salah. Jika semua tabel itu sangat banyak digunakan, itu akan tetap berada dalam memori dengan baik. Jika tidak cukup banyak digunakan untuk tetap dalam memori sesuai dengan algoritma LRU, mungkin ruang memori benar-benar harus dihabiskan untuk sesuatu yang lain. [..]

Anda mungkin juga diminta pertanyaan SO: https://stackoverflow.com/questions/486154/postgresql-tentara-tabel dan mungkin lebih cocok https://stackoverflow.com/questions/407006/need-to-load-the -whole-postgresql-database-into-the-ram

DrColossos
sumber
1
+1 Gagasan yang sama juga berlaku untuk RDBMS lainnya.
gbn
25
Iya dan tidak. Kami mengunci beberapa tabel Oracle di memori karena kami tahu bahwa mereka mungkin tidak sering digunakan, tetapi dalam situasi mereka digunakan, latensi akan menjadi pembunuh. DB harus selalu memberikan kata akhir DBA (contoh lain mengisyaratkan optimizer kueri).
Gayus
35

Postgres 9.4 akhirnya menambahkan ekstensi untuk preload data dari relasi ke OS atau cache buffer database (sesuai pilihan Anda):

pg_prewarm

Ini memungkinkan pencapaian kinerja operasi penuh lebih cepat.

Jalankan sekali di basis data Anda (instruksi terperinci di sini ):

CREATE EXTENSION pg_prewarm;

Maka mudah untuk melakukan preload relasi yang diberikan. Contoh dasar:

SELECT pg_prewarm('my_tbl');

Temukan tabel pertama yang disebutkan my_tbldi jalur pencarian dan muat ke cache buffer Postgres

Atau:

SELECT pg_prewarm('my_schema.my_tbl', 'prefetch');

prefetchmasalah permintaan prefink asinkron ke sistem operasi, jika ini didukung, atau melempar kesalahan sebaliknya. read membaca rentang blok yang diminta; tidak seperti prefetchini, ini sinkron dan didukung pada semua platform dan build, tetapi mungkin lebih lambat. buffermembaca rentang blok yang diminta ke dalam cache buffer database.

Standarnya adalah buffer, yang memiliki dampak terbesar (biaya lebih tinggi, efek terbaik).

Baca manual untuk lebih jelasnya , kutipan dari sana.
Depesz juga membuat blog tentang hal itu.

Erwin Brandstetter
sumber
4

Dalam kasus umum jika Anda memiliki RAM yang cukup, Anda biasanya dapat mempercayai layanan database untuk melakukan pekerjaan yang baik untuk menjaga hal-hal yang Anda gunakan secara teratur dalam RAM. Beberapa sistem memungkinkan Anda untuk mengisyaratkan bahwa tabel harus selalu disimpan dalam RAM (yang berguna untuk tabel bertubuh kecil yang tidak sering digunakan tetapi ketika digunakan, penting bahwa mereka merespons secepat mungkin) tetapi jika pgsql memiliki petunjuk tabel seperti itu Anda harus sangat berhati-hati dalam menggunakannya karena Anda mengurangi jumlah memori yang tersedia untuk melakukan cache apa pun sehingga Anda dapat memperlambat aplikasi secara keseluruhan.

Jika Anda mencari untuk mengunggulkan halaman cache halaman pada startup (misalnya setelah reboot atau operasi pemeliharaan lainnya yang menyebabkan DB melupakan semua yang di-cache) maka tulis skrip yang melakukan hal berikut:

SELECT * FROM <table>
SELECT <primary key fields> FROM <table> ORDER BY <primary key fields>
SELECT <indexed fields> FROM <table> ORDER BY <indexed fields>

(langkah terakhir diulang untuk setiap indeks, atau kursus, dan berhati-hati untuk memiliki bidang dalam klausa ORDER BY dalam urutan yang benar)

Setelah menjalankan di atas, setiap data dan halaman indeks seharusnya sudah dibaca dan demikian juga akan ada dalam cache halaman RAM (untuk saat ini setidaknya). Kami memiliki skrip seperti ini untuk database aplikasi kami, yang dijalankan setelah reboot sehingga pengguna pertama yang masuk ke sistem setelahnya tidak mengalami respons yang lebih lambat. Anda lebih baik menulis skrip semacam itu dengan tangan, daripada memindai tabel definisi db (seperti sys.objects/ sys.indexes/ sys.columnsdi MSSQL), maka Anda dapat memindai indeks yang paling umum digunakan secara selektif daripada memindai semua yang membutuhkan waktu lebih lama.

David Spillett
sumber
3
Ini tidak akan berfungsi, setidaknya di PostgreSQL. Buffer ring kecil (256KB) dialokasikan dari buffer bersama untuk pemindaian sekuensial untuk mencegah seluruh cache buffer digunakan. Lihat github.com/postgres/postgres/blob/master/src/backend/storage/… untuk detailnya. Anda dapat memverifikasi ini dengan melakukan SELECT * dari tabel besar kemudian melihat tabel pg_buffercache (dari ekstensi pg_buffercache).
hbn
@ hbn halo di sana, tetapi orang ini di utas simpanan
scythargon
@scythargon mungkin berakhir di cache OS, ia tidak akan mendapatkannya di cache buffer PostgreSQL. Cobalah apa yang saya sarankan di atas jika Anda tidak percaya kepada saya.
hbn
Di Postgres 9.5, saya mencoba SELECT * FROM schema.tabledan melihatnya memuat seluruh tabel 60GiB ke dalam cache buffer 100GiB PostgreSQL saya.
sudo
1

Saya memiliki masalah yang sama:
Setelah memulai kembali layanan server dan semua data yang diuangkan turun, banyak pertanyaan yang disebut pertama kali di mana benar-benar lambat, menyebabkan kompleksitas spesifik dari pertanyaan, sampai semua indeks dan data yang diperlukan diuangkan. itu artinya, misalnya pengguna harus menekan setiap "item" (1-3 detik waktu eksekutif) dan data terkait dari 50 juta baris, sehingga pengguna tidak akan mengalami penundaan yang tidak diinginkan lagi. Dibutuhkan 3 jam pertama bagi pengguna untuk mengalami gangguan menjengkelkan, sampai data yang paling banyak digunakan dicairkan dan program merusak kedudukan tertinggi dengan kinerja produksi, berakhir pada saat itu, 2 hari beberapa penundaan singkat yang tiba-tiba, ketika memukul data akses pertama yang kurang diakses ... , untuk data statistik dll.

Untuk mengatasi ini, tulis skrip python kecil yang melakukan seleksi pada tabel yang paling berat digunakan dengan indeks besar. Butuh 15 menit untuk menjalankan, dan tidak ada penundaan kinerja.

LongBeard_Boldy
sumber
0

Hmmm, mungkin perintah COPY akan membantu. Cukup jalankan COPY ke stdout dan baca darinya. Dimungkinkan untuk melakukannya menggunakan pg_dump:

pg_dump -U <user> -t <table> <database> > /dev/null

Cara lain adalah menemukan semua file tabel dan menjalankannya cat <files> > /dev/null.

Berikut adalah contoh cara mendapatkan nama file tabel:

# SELECT oid, datname FROM pg_database ;
  oid  |  datname  
-------+-----------                                                                                                                                          
<...>
 16384 | test
-- out of database is 16384
# SELECT oid, relname FROM pg_class WHERE relname like 'fn%';
  oid  | relname 
-------+---------
 24576 | fn
(1 row)
-- oid of our table is 24576

jadi, file tabel adalah / path / ke / pgsql / data / base / 16384/24576 *

Anda juga ingin membaca indeks dan tabel roti bakar juga, mendapatkan oids mereka dengan cara yang sama.

BTW, mengapa Anda membutuhkannya? Saya percaya postgresql dan OS cukup cerdas untuk menyimpan cache data terpanas dan mempertahankannya. efisiensi cache.

rvs
sumber
0

Saya menggunakan ramdrive dari QSoft, yang mengacu sebagai ramdisk tercepat untuk Windows. Saya baru saja digunakan

initdb -D e:\data

di mana e: \ adalah tempat RamDisk.

David
sumber
5
PG pada Windows adalah pilihan yang cukup berani untuk situs produksi karena cara ini lebih lambat pada Windows daripada pada * nix (terlepas dari RAM).
DrColossos