Як би ви перевірили, чи потрібен екземпляр DB-файлу postgresql більше оперативної пам’яті для обробки поточних робочих даних?
Як би ви перевірили, чи потрібен екземпляр DB-файлу postgresql більше оперативної пам’яті для обробки поточних робочих даних?
Відповіді:
Якщо ви все на 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 ГБ і все ще мати можливість для подальшого зростання.
Я зробив цей 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