Bagaimana saya bisa memeriksa apakah DB saya membutuhkan lebih banyak RAM?

11

Bagaimana Anda memeriksa jika instance DB postgresql Anda membutuhkan lebih banyak memori RAM untuk menangani data kerjanya saat ini?

SDReyes
sumber
8
Tidak perlu memeriksa, Anda selalu membutuhkan lebih banyak RAM. :)
Alex Howansky
1
Bukan pertanyaan pemrograman, saya memilih untuk memindahkannya ke ServerFault.
GManNickG
1
Saya bukan DBA, tapi saya akan mulai dengan melihat pertanyaan umum yang ada di tepi hash bergabung bukan gabungan digabung lingkaran. Ada beberapa penyetelan konfigurasi db yang dapat Anda lakukan yang dapat memengaruhi seberapa banyak memori yang tersedia untuk kueri tertentu [memeriksa dokumen atau mengirim email ke milis adalah saran saya]. Ini juga dapat berguna untuk melihat apakah Anda memiliki cukup RAM untuk menyimpan tabel yang sering digunakan dalam cache. Tetapi pada akhirnya, kecuali SELURUH DB Anda cocok dengan RAM Anda bisa menggunakan lebih banyak. :)

Jawaban:

14

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.

Matthew Wood
sumber
9

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

masukkan deskripsi gambar di sini

Kristen
sumber
1

Ini juga berfungsi, seperti yang dikatakan dalam dokumen Heroku:

SELECT
    'cache hit rate' AS name,
     sum(heap_blks_hit) / (sum(heap_blks_hit) + sum(heap_blks_read)) AS ratio
FROM pg_statio_user_tables;
Felipe
sumber