web-dev-qa-db-fra.com

Comment récupérer de l'espace disque sur PostgreSQL?

J'ai une installation locale de la base de données 9.1 avec quelques tables qui avaient cca. 300 millions d'enregistrements et la base de données est passée à environ 20 Go. Ensuite, j'ai publié delete from commande pour supprimer tous les enregistrements de celui-ci (j'aurais dû utiliser truncate, mais je ne le savais pas). J'ai donc fait un vide complet sur ma base de données pour récupérer de l'espace disque, mais cela n'aide pas. Mon problème semble identique à celui-ci , mais aucune solution n'est fournie. J'ai déjà vérifié ce fil et la documentation sur "récupérer de l'espace disque" , mais je ne trouve toujours pas de solution. J'utilise ce code pour obtenir la taille de toutes les tables

 SELECT nspname || '.' || relname AS "relation",
 pg_size_pretty(pg_total_relation_size(C.oid)) AS "total_size"
 FROM pg_class C
 LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
 WHERE nspname NOT IN ('pg_catalog', 'information_schema')
 AND C.relkind <> 'i'
 AND nspname !~ '^pg_toast'
 ORDER BY pg_total_relation_size(C.oid) DESC
 LIMIT 15;

Cependant, pour un total inférieur à 1 Go

SELECT pg_database.datname, pg_size_pretty(pg_database_size(pg_database.datname)) AS size FROM pg_database 

affiche toujours environ 20 Go. Tout conseil très apprécié.

26
arcull

Bien que vous ne l'ayez pas déclaré, je suppose, d'après vos références aux documents que vous avez suivis, que vous avez effectué un VIDE COMPLET sur la base de données et/ou les tables affectées. Vous n'avez pas non plus spécifié quelle version postgresql vous utilisez - je suppose que c'est> 9.0 (VACUUM FULL s'est comporté différemment avant cela).

VACUUM FULL réécrira les tableaux affectés dans de nouveaux fichiers, puis supprimera les anciens fichiers. Cependant, si un processus a toujours l'ancien fichier ouvert, le système d'exploitation ne supprimera pas réellement le fichier - jusqu'à ce que le dernier processus l'ait fermé.

Si possible, le redémarrage de la base de données garantirait la fermeture de tous les fichiers ouverts.

Si ce n'est pas pratique, vous pourrez peut-être vérifier si c'est votre problème et découvrir quel processus a les fichiers ouverts.

Si vous utilisez Linux (ou la plupart des autres systèmes de type Unix), vous pouvez utiliser la commande 'lsof' pour obtenir une liste de tous les fichiers ouverts dans tous les processus. Les fichiers ouverts mais qui ont depuis été supprimés auront "(supprimé)" ajouté au nom de fichier. Ainsi, vous pouvez grep la sortie de lsof, à la recherche de fichiers supprimés, comme ceci:

Sudo lsof -u postgres | grep 'deleted'

Si cela identifie les processus qui ont toujours les anciens fichiers ouverts, vous pouvez utiliser pg_terminate_backend pour terminer ce processus:

SELECT pg_terminate_backend(xxx);

où xxx est le PID du processus, trouvé dans la sortie lsof.

Si vous utilisez Windows, le même principe pourrait s'appliquer, car postgres ouvre les fichiers à l'aide de l'indicateur FILE_SHARE_DELETE, ce qui lui permet de supprimer les fichiers ouverts dans un autre processus. La commande ' handle ' est l'équivalent approximatif de lsof, bien que je ne sais pas si vous pouvez dire si les fichiers sont supprimés ou non, donc un travail supplémentaire pourrait être nécessaire.

C'est une autre question de savoir pourquoi de tels processus s'accrocheraient aux anciens descripteurs de fichiers. Cependant, dans le thread que vous avez cité dans votre question, Tom Lane semble impliquer que cela peut arriver.

23
harmic