Як я можу перевірити, чи потрібно моїй БД більше оперативної пам’яті?


11

Як би ви перевірили, чи потрібен екземпляр DB-файлу postgresql більше оперативної пам’яті для обробки поточних робочих даних?


8
Не потрібно перевіряти, завжди потрібно більше оперативної пам’яті. :)
Олексій Хованський

1
Не питання програмування, я голосую за перенесення його до ServerFault.
GManNickG

1
Я не DBA, але я б почав з того, щоб побачити будь-які загальні запити на межі того, що хеш-об'єднання замість об'єднаного вкладеного циклу. Ви можете зробити налаштування db-конфігурації, що може вплинути на кількість пам'яті, доступної для будь-якого конкретного запиту [перевірити документи або надіслати електронною поштою список розсилки - це моя пропозиція]. Також може бути корисно побачити, чи є у вас достатньо оперативної пам’яті, щоб зберегти кешовані часто використовувані таблиці. Але в кінцевому підсумку, якщо ваш ВСІЙ БД не вписується в оперативну пам'ять, ви могли б використовувати більше. :)

Відповіді:


14

Якщо ви все на Linux, ваша загальна фізична оперативна пам’ять повинна бути більшою за розмір вашої бази даних на диску, щоб мінімізувати введення-виведення. Врешті-решт, вся база даних опиниться в кеш-пам'яті зчитування ОС, а введення-виведення обмежиться внесенням змін на диск. Я вважаю за краще знайти розмір БД, запустивши "du -shc $ PGDATA / base" - цей метод об'єднує всі бази даних в одне число. Поки ти більший за це, має бути добре.

Крім того, ви можете подивитися на швидкість звернення кешу для купи та індексу блоків. Вони вимірюють швидкість звернень до загальних буферів PostgreSQL. Цифри можуть бути трохи оманливими - хоча, можливо, це було пропуском кеша загальних буферів, це все одно може бути хітом в кеш-пам'яті зчитування ОС. Тим не менш, звернення в загальні буфери все ще менш дорогі, ніж звернення в кеш-пам'ять зчитування ОС (які, в свою чергу, дешевші на пару порядків, ніж повернення на диск).

Для того, щоб переглянути швидкість звернення до загальних буферів, я використовую цей запит:

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;

Це дає вам 25 найгірших порушників, де кеш-пам'ять буфера пропущена для всіх таблиць, де хоча б один блок потрібно було отримати з "диска" (знову ж таки, це може бути кеш читання ОС або фактичний диск вводу / виводу диска). Ви можете збільшити значення в пункті WHERE або додати іншу умову для heap_blks_hit для фільтрації рідко використовуваних таблиць.

Цей самий основний запит можна використовувати для перевірки загальної частоти звернень за індексом за таблицею шляхом глобальної заміни рядка "heap" на "idx". Погляньте на pg_statio_user_indexes, щоб отримати розбивку за індексом.

Коротка примітка про спільні буфери: хорошим правилом для цього в Linux є встановлення параметра конфігурації shared_buffers на 1/4 оперативної пам’яті, але не більше 8 ГБ. Це не важке і швидке правило, а скоріше хороша відправна точка для налаштування сервера. Якщо у вашій базі даних всього 4 ГБ, а у вас є 32 ГБ сервера, 8 ГБ загальних буферів насправді є надмірними, і ви повинні мати можливість встановити це на 5 або 6 ГБ і все ще мати можливість для подальшого зростання.


9

Я зробив цей SQL, щоб показати співвідношення таблиць та дискових показів:

-- 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

введіть тут опис зображення


1

Він також працює, як сказано в документі 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;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.