Comment puis-je vérifier si ma base de données a besoin de plus de RAM?

11

Comment vérifieriez-vous si votre instance de base de données postgresql a besoin de plus de mémoire RAM pour gérer ses données de travail actuelles?

SDReyes
la source
8
Pas besoin de vérifier, vous avez toujours besoin de plus de RAM. :)
Alex Howansky
1
Pas une question de programmation, je vote pour le déplacer vers ServerFault.
GManNickG
1
Je ne suis pas un DBA, mais je commencerais par voir que toutes les requêtes courantes sont sur le point d'être jointes par hachage au lieu de fusionner imbriquées en boucle. Il y a des réglages de configuration de base de données que vous pouvez faire qui pourraient également affecter la quantité de mémoire disponible pour une requête particulière [vérifiez les documents ou envoyez un e-mail à la liste de diffusion est ma suggestion]. Il peut également être utile de voir si vous disposez de suffisamment de RAM pour conserver en mémoire cache les tables couramment utilisées. Mais en fin de compte, à moins que votre DB ENTIER ne tienne dans la RAM, vous pourriez en utiliser davantage. :)

Réponses:

14

Si tout ce que vous êtes sur Linux, votre RAM physique totale doit être supérieure à la taille de votre base de données sur le disque afin de minimiser les E / S. Finalement, toute la base de données sera dans le cache de lecture du système d'exploitation et les E / S seront limitées à la validation des modifications sur le disque. Je préfère trouver la taille de la base de données en exécutant "du -shc $ PGDATA / base" - cette méthode regroupe toutes les bases de données en un seul numéro. Tant que vous êtes plus grand que ça, ça devrait aller.

En outre, vous pouvez consulter le taux d'accès au cache des récupérations de tas et d'index. Ceux-ci mesurent le taux de hits dans les tampons partagés de PostgreSQL. Les chiffres peuvent être un peu trompeurs - même si cela a pu être un échec dans le cache des tampons partagés, il peut toujours être un succès dans le cache de lecture du système d'exploitation. Pourtant, les hits dans les tampons partagés sont toujours moins chers que les hits dans le cache de lecture du système d'exploitation (qui, à leur tour, sont moins chers de quelques ordres de grandeur que d'avoir à revenir sur le disque).

Afin de regarder le taux de réussite des tampons partagés, j'utilise cette requête:

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;

Cela vous donne les 25 pires contrevenants où le cache tampon est manquant pour toutes les tables où au moins un bloc a dû être récupéré à partir du "disque" (encore une fois, qui pourrait être le cache de lecture du système d'exploitation ou les E / S de disque réelles). Vous pouvez augmenter la valeur dans la clause WHERE ou ajouter une autre condition pour que heap_blks_hit filtre les tables rarement utilisées.

La même requête de base peut être utilisée pour vérifier le taux de réussite d'index total par table en remplaçant globalement la chaîne "heap" par "idx". Jetez un œil à pg_statio_user_indexes pour obtenir une ventilation par index.

Une note rapide sur les tampons partagés: une bonne règle de base pour cela sous Linux est de définir le paramètre de configuration shared_buffers sur 1/4 de RAM, mais pas plus de 8 Go. Ce n'est pas une règle stricte et rapide, mais plutôt un bon point de départ pour régler un serveur. Si votre base de données ne fait que 4 Go et que vous avez un serveur de 32 Go, 8 Go de tampons partagés sont en fait exagérés et vous devriez pouvoir définir cela à 5 ou 6 Go et avoir encore de la place pour une croissance future.

Matthew Wood
la source
9

J'ai fait ce SQL pour montrer le rapport tables / disques:

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

entrez la description de l'image ici

Christian
la source
1

Cela fonctionne également, comme indiqué dans le document 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
la source