Récemment, j'ai eu un serveur PostgreSQL 8.2.11 mis à niveau vers 8.4 afin de profiter des fonctionnalités d'autovacuum et d'être en ligne avec 30 autres autres serveurs PGSQL. Cela a été fait par un groupe informatique distinct qui gère le matériel, nous n'avons donc pas beaucoup de choix sur les autres mises à niveau (ne verront pas 9+ pendant un certain temps). Le serveur existe dans un environnement très fermé (réseau isolé, privilèges root limités) et fonctionne sur RHEL5.5 (i686). Après la mise à niveau, la base de données a constamment augmenté de 5 à 6 Go par jour. Normalement, la base de données dans son ensemble est d'environ 20 Go; actuellement, il est d'environ 89 Go. Nous avons quelques autres serveurs qui exécutent des bases de données équivalentes et synchronisent réellement les enregistrements entre eux via une application tierce (dont je n'ai pas accès aux rouages internes). Les autres bases de données font ~ 20 Go comme il se doit.
En exécutant le SQL suivant, il est assez évident qu'il y a un problème avec une table particulière et, plus spécifiquement, sa table TOAST.
SELECT nspname || '.' || relname AS "relation",
pg_size_pretty(pg_relation_size(C.oid)) AS "size"
FROM pg_class C
LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
WHERE nspname NOT IN ('pg_catalog', 'information_schema')
ORDER BY pg_relation_size(C.oid) DESC
LIMIT 20;
Ce qui produit:
relation | Taille ------------------------------------ + --------- pg_toast.pg_toast_16874 | 89 Go fews00.warmstates | 1095 Mo ... (20 rangées)
Cette table TOAST est destinée à une table appelée "timeseries" qui enregistre de gros enregistrements de données blobées. Un SUM(LENGTH(blob)/1024./1024.)
de tous les enregistrements de la série temporelle donne ~ 16 Go pour cette colonne. Il ne devrait y avoir aucune raison que la table TOAST de cette table soit aussi grande qu'elle l'est.
J'ai effectué un VACUUM FULL VERBOSE ANALYZE timeseries
, et le vide se termine sans erreur.
INFO: passer l'aspirateur "pg_toast.pg_toast_16874"
INFO: "pg_toast_16874": trouvé 22483 versions amovibles, 10475318 non amovibles en 10448587 pages
DÉTAIL: aucune version de ligne morte ne peut encore être supprimée.
Les versions de ligne non amovibles ont une longueur de 37 à 2036 octets.
Il y avait 20121422 pointeurs d'article inutilisés.
L'espace libre total (y compris les versions de lignes amovibles) est de 0 octet. 4944885 pages sont ou deviendront vides, y compris 0 à la fin du tableau. 4944885 pages contenant 0 octets libres sont des destinations de déplacement potentielles.
CPU 75.31s / 29.59u sec écoulé 877.79 sec.
INFO: l'index "pg_toast_16874_index" contient désormais 10475318 versions de lignes sur 179931 pages.
DÉTAIL: 23884 versions de lignes d'index ont été supprimées.
Les pages d'index 101623 ont été supprimées, 101623 sont actuellement réutilisables.
CPU 1.35s / 2.46u sec écoulé 21.07 sec.
REINDEXer la table qui a libéré un certain espace (~ 1 Go). Je ne peux pas CLUSTER la table car il n'y a pas assez d'espace sur le disque pour le processus, et j'attends de reconstruire la table entièrement car j'aimerais savoir pourquoi elle est tellement plus grande que les bases de données équivalentes que nous avons.
Exécutez une requête du wiki PostgreSQL ici - "Afficher la base de données Bloat" , et voici ce que j'obtiens:
base de données_actuelle | schemaname | nom_table | tbloat | wastedbytes | iname | ibloat | gaspillages ----------------- + ------------ + ------------------- ------------- + -------- + ------------- + ------------- -------------------- + -------- + -------------- ptrdb04 | fews00 | timeseries | 1.0 | 0 | idx_timeseries_synchlevel | 0,0 | 0 ptrdb04 | fews00 | timeseries | 1.0 | 0 | idx_timeseries_localavail | 0,0 | 0 ptrdb04 | fews00 | timeseries | 1.0 | 0 | idx_timeseries_expirytime | 0,0 | 0 ptrdb04 | fews00 | timeseries | 1.0 | 0 | idx_timeseries_expiry_null | 0,0 | 0 ptrdb04 | fews00 | timeseries | 1.0 | 0 | uniq_localintid | 0,0 | 0 ptrdb04 | fews00 | timeseries | 1.0 | 0 | pk_timeseries | 0,1 | 0 ptrdb04 | fews00 | idx_timeseries_expiry_null | 0,6 | 0 | ? | 0,0 | 0
Il semble que la base de données ne considère pas du tout cet espace comme "vide", mais je ne vois tout simplement pas d'où vient tout l'espace disque!
Je soupçonne que ce serveur de base de données décide d'utiliser 4 à 5 fois plus d'espace disque pour enregistrer les mêmes enregistrements extraits des autres serveurs de données. Ma question est la suivante: existe-t-il un moyen de vérifier la taille du disque physique d'une ligne? Je voudrais comparer la taille d'une ligne de cette base de données à une autre base de données "saine".
Merci pour toute l'aide que vous pourrez fournir!
MISE À JOUR 1
J'ai fini par reconstruire la table à partir d'un schéma vidé en raison de sa taille (je ne pouvais pas la laisser seule un autre jour). Après avoir synchronisé les données, via le processus de synchronisation du logiciel, la table TOAST était ~ 35 Go; cependant, je ne pouvais en représenter que 9 Go à partir de cette colonne blob qui devrait être la plus longue en termes de valeurs. Je ne sais pas d'où vient l'autre 26 Go. CLUSTERed, VACUUM FULLed et REINDEXed in vain. Les fichiers postgresql.conf entre les serveurs de données locaux et distants sont exactement les mêmes. Y a-t-il une raison pour laquelle cette base de données essaie de stocker chaque enregistrement avec un espace plus grand sur le disque?
MISE À JOUR 2 - Corrigé
J'ai finalement décidé de reconstruire complètement la base de données à partir de zéro, allant même jusqu'à réinstaller les packages PostgreSQL84 sur le système. Le chemin d'accès à la base de données a été réinitialisé et les espaces disque logiques ont été nettoyés. Le processus de synchronisation des logiciels tiers a repeuplé les tables, et la taille finale s'est révélée être ~ 12 Go ! Malheureusement, cela ne permet en aucune façon de résoudre la source exacte du problème. Je vais le regarder pendant un jour ou deux et voir s'il y a des différences majeures avec la façon dont la base de données revitalisée gère la table TOAST et publier ces résultats ici.
Taille de la relation
ptrdb04=> SELECT nspname || '.' || relname AS "relation",
ptrdb04-> pg_size_pretty(pg_relation_size(C.oid)) AS "size"
ptrdb04-> FROM pg_class C
ptrdb04-> LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
ptrdb04-> WHERE nspname NOT IN ('pg_catalog', 'information_schema')
ptrdb04-> ORDER BY pg_relation_size(C.oid) DESC
ptrdb04-> LIMIT 2;
relation | taille
------------------------- + ---------
pg_toast . pg_toast_17269 | 18 Go
fews00 . warmstates | 1224 Mo
( 2 rangées )
VACUUM VERBOSE ANALYZE timeseries;
INFO: "séries temporelles": trouvé 12699 versions de lignes amovibles, 681961 non amovibles dans 58130 sur 68382 pages DÉTAIL: aucune version de ligne morte ne peut encore être supprimée. Il y avait 105847 pointeurs d'articles inutilisés. 0 pages sont entièrement vides. CPU 0,83 s / 2,08 u sec écoulé 33,36 s. INFO: passer l'aspirateur "pg_toast.pg_toast_17269" INFO: index analysé "pg_toast_17269_index" pour supprimer les versions de ligne 2055849 DÉTAIL: CPU 0.37s / 2.92u sec écoulé 13.29 sec. INFO: «pg_toast_17269»: versions de ligne 2055849 supprimées dans 518543 pages DÉTAIL: CPU 8.60s / 3.21u sec écoulé 358.42 sec. INFO: l'index "pg_toast_17269_index" contient désormais 7346902 versions de ligne sur 36786 pages DÉTAIL: les versions de la ligne d'index 2055849 ont été supprimées. 10410 pages d'index ont été supprimées, 5124 sont actuellement réutilisables. CPU 0,00 s / 0,00 u s écoulé 0,01 s. INFO: "pg_toast_17269": trouvé 1286128 amovibles, 2993389 versions de lignes non amovibles en 1257871 sur 2328079 pages DÉTAIL: aucune version de ligne morte ne peut encore être supprimée. Il y avait 18847 pointeurs d'objets inutilisés. 0 pages sont entièrement vides. CPU 26.56s / 13.04u sec écoulé 714.97 sec. INFO: analyse de "fews00.timeseries" INFO: "timeseries": numérisé 30000 de 68382 pages, contenant 360192 lignes en direct et 0 lignes mortes; 30000 lignes dans l'échantillon, 821022 lignes totales estimées
La seule différence notable après la reconstruction (autre que l'utilisation du disque) est
INFO: "pg_toast_17269": trouvé 1286128 amovible, 2993389 versions de ligne non amoviblecomme @CraigRinger l'a mentionné dans un commentaire. Le nombre de lignes non amovibles est beaucoup plus petit qu'auparavant.
Nouvelle question: d' autres tables peuvent-elles affecter la taille d'une autre table? (via des clés étrangères et autres) La reconstruction de la table n'a rien fait, mais la reconstruction de la base de données entière s'est avérée résoudre le problème.