VACUUM
ne renvoie généralement pas d'espace disque au système d'exploitation, sauf dans certains cas particuliers.
D'après les documents:
La forme standard de
VACUUM
supprime les versions de lignes mortes dans les tables et les index et marque l'espace disponible pour une réutilisation future. Cependant, il ne restituera pas l'espace au système d'exploitation, sauf dans le cas spécial où une ou plusieurs pages à la fin d'une table deviennent entièrement libres et un verrou de table exclusif peut être facilement obtenu. En revanche,VACUUM FULL
compacte activement les tables en écrivant une nouvelle version complète du fichier de table sans espace mort. Cela minimise la taille de la table, mais peut prendre beaucoup de temps. Il nécessite également de l'espace disque supplémentaire pour la nouvelle copie de la table, jusqu'à la fin de l'opération.
La question est: comment cette base de données peut-elle indiquer quand one or more pages at the end of a table become entirely free
être atteint? Cela peut être fait via VACUUM FULL
, mais je n'ai pas assez d'espace pour l'implémenter. Y a-t-il donc d'autres possibilités?
Pour renvoyer de l'espace au système d'exploitation, utilisez VACUUM FULL
. Tout en y étant, je suppose que vous exécutez VACUUM FULL ANALYZE
. je cite le manuel :
FULL
Sélectionne le vide "complet", qui peut récupérer plus d'espace , mais prend beaucoup plus de temps et verrouille exclusivement la table. Cette méthode nécessite également de l'espace disque supplémentaire, car elle écrit une nouvelle copie de la table et ne libère pas l'ancienne copie tant que l'opération n'est pas terminée. Habituellement, cela ne doit être utilisé que lorsqu'une quantité importante d'espace doit être récupérée à l'intérieur de la table.
Accentuation sur moi.
CLUSTER
y parvient également comme effet collatéral.
Plain VACUUM
n'atteint normalement pas votre objectif ( "une ou plusieurs pages à la fin d'un tableau entièrement gratuites"). Il ne réorganise pas les lignes et n'élague que les pages vides de la fin physique du fichier lorsque l'occasion se présente - comme l'indique votre citation du manuel.
Vous pouvez obtenir des pages vides à la fin du fichier physique lorsque vous INSERT
un lot de lignes et DELETE
avant que d'autres tuples ne soient ajoutés. Ou cela peut arriver par coïncidence si suffisamment de lignes sont supprimées.
Il existe également des paramètres spéciaux qui peuvent empêcher VACUUM FULL
De récupérer de l'espace. Voir:
La colonne système ctid
représente la position physique d'une ligne. Vous devez comprendre cette colonne:
Nous pouvons travailler avec cela et préparer un tableau en supprimant toutes les lignes de la dernière page:
DELETE FROM tbl t
USING (
SELECT (split_part(ctid::text, ',', 1) || ',0)')::tid AS min_tid
, (split_part(ctid::text, ',', 1) || ',65535)')::tid AS max_tid
FROM tbl
ORDER BY ctid DESC
LIMIT 1
) d
WHERE t.ctid BETWEEN d.min_tid AND d.max_tid;
Maintenant, la dernière page est vide. Cela ignore les écritures simultanées. Soit vous êtes le seul à écrire sur cette table, soit vous devez prendre un verrou d'écriture pour éviter les interférences.
La requête est optimisée pour identifier rapidement les lignes éligibles. Le deuxième nombre d'un tid
est l'index de tuple stocké en tant que non signé int2
, Et 65535
Est le maximum pour ce type (2^16 - 1
), C'est donc le limite supérieure sûre.
SQL Fiddle (réutilisation d'une table simple à partir d'un cas différent.)
Outils pour mesurer la taille des lignes/tableaux:
Vous avez besoin de marge de manœuvre sur le disque pour chacune de ces opérations. Il existe également l'outil de communauté pg_repack
en remplacement de VACUUM FULL
/CLUSTER
. Il évite les verrous exclusifs mais a également besoin d'espace libre pour fonctionner. Le manuel:
Nécessite un espace disque libre deux fois plus grand que les tables et index cibles.
En dernier recours, vous pouvez exécuter un cycle de vidage/restauration. Cela supprime également tous les ballonnements des tables et des index. Question étroitement liée:
La réponse là-bas est assez radicale. Si votre situation le permet (pas de clés étrangères ou d'autres références empêchant les suppressions de lignes), et pas d'accès simultané à la table), vous pouvez simplement:
Vider la table sur le disque en se connectant à partir d'un ordinateur distant avec beaucoup d'espace disque (-a
Pour --data-only
):
Depuis le shell distant, les données de la table de vidage:
pg_dump -h <Host_name> -p <port> -t mytbl -a mydb > db_mytbl.sql
Dans une session pg, TRUNCATE
la table:
-- drop all indexes and constraints here for best performance
TRUNCATE mytbl;
À partir du shell distant, restaurez dans la même table:
psql -h <Host_name> -p <port> mydb -f db_mytbl.sql
-- recreate all indexes and constraints here
Il est maintenant libre de toute ligne morte ou ballonnement.
Mais peut-être pouvez-vous avoir cela plus simple?
Pouvez-vous faire suffisamment d'espace sur le disque en supprimant (déplaçant) des fichiers non liés?
Pouvez-vous VACUUM FULL
Des tables plus petites en premier, une par une, libérant ainsi suffisamment d'espace disque?
Pouvez-vous exécuter REINDEX TABLE
ou REINDEX INDEX
Pour libérer de l'espace disque des index gonflés?
Quoi que vous fassiez, ne soyez pas téméraire . En cas de doute, sauvegardez tout d'abord dans un emplacement sécurisé.