Bagaimana Anda memeriksa jika instance DB postgresql Anda membutuhkan lebih banyak memori RAM untuk menangani data kerjanya saat ini?
Bagaimana Anda memeriksa jika instance DB postgresql Anda membutuhkan lebih banyak memori RAM untuk menangani data kerjanya saat ini?
Jawaban:
Jika semua Anda menggunakan Linux, total RAM fisik Anda harus lebih besar dari ukuran basis data Anda pada disk untuk meminimalkan I / O. Akhirnya seluruh database akan berada dalam cache read OS dan I / O akan terbatas untuk melakukan perubahan pada disk. Saya lebih suka menemukan ukuran DB dengan menjalankan "du -shc $ PGDATA / base" - metode yang mengumpulkan semua database menjadi satu nomor. Selama Anda lebih besar dari itu, itu akan baik-baik saja.
Selain itu, Anda dapat melihat tingkat hit cache dari heap dan indeks ambil blok. Ini mengukur tingkat klik ke buffer bersama PostgreSQL. Angka-angka ini bisa sedikit menyesatkan - meskipun mungkin ada kesalahan dalam cache buffer bersama, itu mungkin masih menjadi hit di cache read OS. Namun, hit di buffer bersama masih lebih murah daripada hit di cache baca OS (yang, pada gilirannya, lebih murah oleh beberapa pesanan besar daripada harus kembali ke disk).
Untuk melihat tingkat klik buffer bersama, saya menggunakan kueri ini:
SELECT relname, heap_blks_read, heap_blks_hit,
round(heap_blks_hit::numeric/(heap_blks_hit + heap_blks_read),3)
FROM pg_statio_user_tables
WHERE heap_blks_read > 0
ORDER BY 4
LIMIT 25;
Ini memberi Anda 25 pelanggar terburuk teratas di mana cache buffer tidak terjawab untuk semua tabel di mana setidaknya satu blok harus diambil dari "disk" (sekali lagi, yang bisa berupa cache pembacaan OS atau I / O disk aktual). Anda dapat meningkatkan nilai dalam klausa WHERE atau menambahkan kondisi lain untuk heap_blks_hit untuk memfilter tabel yang jarang digunakan.
Kueri dasar yang sama dapat digunakan untuk memeriksa tingkat hit indeks total per tabel dengan mengganti string "heap" secara global dengan "idx". Lihatlah pg_statio_user_indexes untuk mendapatkan rincian per-indeks.
Catatan singkat tentang buffer bersama: aturan praktis yang baik untuk ini di Linux adalah mengatur parameter konfigurasi shared_buffers ke 1/4 dari RAM, tetapi tidak lebih dari 8GB. Ini bukan aturan yang sulit dan cepat, tetapi lebih merupakan titik awal yang baik untuk menyetel server. Jika database Anda hanya 4GB dan Anda memiliki server 32GB, 8GB buffer bersama sebenarnya berlebihan dan Anda harus dapat mengatur ini ke 5 atau 6 GB dan masih memiliki ruang untuk pertumbuhan di masa depan.
Saya membuat SQL ini untuk menampilkan tabel vs disk hits rasio:
-- perform a "select pg_stat_reset();" when you want to reset counter statistics
with
all_tables as
(
SELECT *
FROM (
SELECT 'all'::text as table_name,
sum( (coalesce(heap_blks_read,0) + coalesce(idx_blks_read,0) + coalesce(toast_blks_read,0) + coalesce(tidx_blks_read,0)) ) as from_disk,
sum( (coalesce(heap_blks_hit,0) + coalesce(idx_blks_hit,0) + coalesce(toast_blks_hit,0) + coalesce(tidx_blks_hit,0)) ) as from_cache
FROM pg_statio_all_tables --> change to pg_statio_USER_tables if you want to check only user tables (excluding postgres's own tables)
) a
WHERE (from_disk + from_cache) > 0 -- discard tables without hits
),
tables as
(
SELECT *
FROM (
SELECT relname as table_name,
( (coalesce(heap_blks_read,0) + coalesce(idx_blks_read,0) + coalesce(toast_blks_read,0) + coalesce(tidx_blks_read,0)) ) as from_disk,
( (coalesce(heap_blks_hit,0) + coalesce(idx_blks_hit,0) + coalesce(toast_blks_hit,0) + coalesce(tidx_blks_hit,0)) ) as from_cache
FROM pg_statio_all_tables --> change to pg_statio_USER_tables if you want to check only user tables (excluding postgres's own tables)
) a
WHERE (from_disk + from_cache) > 0 -- discard tables without hits
)
SELECT table_name as "table name",
from_disk as "disk hits",
round((from_disk::numeric / (from_disk + from_cache)::numeric)*100.0,2) as "% disk hits",
round((from_cache::numeric / (from_disk + from_cache)::numeric)*100.0,2) as "% cache hits",
(from_disk + from_cache) as "total hits"
FROM (SELECT * FROM all_tables UNION ALL SELECT * FROM tables) a
ORDER BY (case when table_name = 'all' then 0 else 1 end), from_disk desc