¿Cómo puedo verificar si mi DB necesita más RAM?

11

¿Cómo comprobaría si su instancia de DB postgresql necesita más memoria RAM para manejar sus datos de trabajo actuales?

SDReyes
fuente
8
No es necesario verificar, siempre necesita más RAM. :)
Alex Howansky
1
No es una pregunta de programación, estoy votando para moverlo a ServerFault.
GManNickG
1
No soy un DBA, pero comenzaría por ver que cualquier consulta común está al borde de unir hash en lugar de fusionar anidado en bucle. Hay algunos ajustes de configuración de db que puede hacer que podrían afectar la cantidad de memoria disponible para cualquier consulta en particular [consulte los documentos o envíe un correo electrónico a la lista de correo es mi sugerencia]. También puede ser útil para ver si tiene suficiente RAM para mantener en caché las tablas de uso común. Pero en última instancia, a menos que su DB COMPLETO se ajuste a la RAM, podría usar más. :)

Respuestas:

14

Si todo lo que está en Linux, su RAM física total debe ser mayor que el tamaño de su base de datos en el disco para minimizar la E / S. Finalmente, toda la base de datos estará en la caché de lectura del sistema operativo y la E / S se limitará a confirmar los cambios en el disco. Prefiero encontrar el tamaño de la base de datos ejecutando "du -shc $ PGDATA / base", ese método agrega todas las bases de datos en un solo número. Mientras seas más grande que eso, debería estar bien.

Además, puede ver la tasa de aciertos de caché de las capturas de bloque de índice y montón. Estos miden la tasa de visitas a los buffers compartidos de PostgreSQL. Los números pueden ser un poco engañosos, aunque puede haber sido un error en la memoria caché de buffers compartidos, aún puede ser un éxito en la memoria caché de lectura del sistema operativo. Aún así, los hits en los buffers compartidos son aún menos costosos que los hits en la memoria caché de lectura del sistema operativo (que, a su vez, son menos costosos en un par de órdenes de magnitud que tener que volver al disco).

Para ver la tasa de aciertos de los buffers compartidos, utilizo esta consulta:

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;

Esto le da a los 25 peores delincuentes principales donde se pierde la memoria caché del búfer para todas las tablas donde al menos un bloque tuvo que ser recuperado del "disco" (nuevamente, que podría ser la memoria caché de lectura del sistema operativo o la E / S del disco real). Puede aumentar el valor en la cláusula WHERE o agregar otra condición para heap_blks_hit para filtrar las tablas poco utilizadas.

La misma consulta básica se puede utilizar para verificar la tasa de aciertos del índice total por tabla reemplazando globalmente la cadena "montón" con "idx". Eche un vistazo a pg_statio_user_indexes para obtener un desglose por índice.

Una nota rápida sobre los buffers compartidos: una buena regla general para esto en Linux es establecer el parámetro de configuración shared_buffers en 1/4 de RAM, pero no más de 8GB. Esta no es una regla estricta, sino un buen punto de partida para ajustar un servidor. Si su base de datos es de solo 4 GB y tiene un servidor de 32 GB, 8 GB de memorias intermedias compartidas en realidad es excesivo y debería poder configurarlo en 5 o 6 GB y aún tener espacio para el crecimiento futuro.

Matthew Wood
fuente
9

Hice este SQL para mostrar las tablas vs la proporción de aciertos de disco:

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

ingrese la descripción de la imagen aquí

cristiano
fuente
1

También funciona, como se dijo en Heroku doc:

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
fuente