web-dev-qa-db-fra.com

VACUUM renvoyant de l'espace disque au système d'exploitation

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?

22

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:

Préparer des pages vides à la fin d'un tableau pour les tests

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:

Disque plein

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

33
Erwin Brandstetter