Estimer la taille des Large Objects par table¶
Problématique¶
Les Large Objects ne sont pas « attribués » à une table dans le dictionnaire de données.
Ce sont des objets indépendants, stockés dans pg_largeobject
, et indexés par un oid
,
qui est manipulé par les fonctions lo_*
.
Le lien avec la/les table stockant ces oid
est donc très faible
(pas de relation de clé étrangère). Par ailleurs, tous les Large Objects sont stockés dans une seule et même table,
ce qui rend difficile le chiffrage de la volumétrie des Large Objects associés à une table particulière.
Solution¶
Il est impossible de résoudre le problème avec une simple requête, il faut absolument utiliser une fonction : on ne sait pas dans quelles tables se trouvent les champs oid
susceptibles de contenir des liens vers des large objects. Cette fonction retourne donc les oid
contenus dans la base, et la table d’où ils proviennent :
CREATE OR REPLACE FUNCTION lo_oids ( )
RETURNS TABLE ( loid oid, tableoid oid)
LANGUAGE plpgsql
AS $function$
DECLARE
vcurseur record;
vloid oid;
BEGIN
FOR vcurseur IN SELECT attrelid, attname
FROM pg_attribute
WHERE atttypid IN (SELECT oid from pg_type where typname in ('oid', 'lo'))
AND attnum > 0
AND NOT attisdropped
AND attrelid IN (SELECT oid
FROM pg_class
WHERE relnamespace NOT IN (SELECT oid
FROM pg_namespace
WHERE nspname IN ('pg_catalog')
)
AND relkind = 'r'
)
LOOP
-- On a un curseur qui contient l'id de la table, et le nom de l'attribut
tableoid = vcurseur.attrelid;
FOR loid IN EXECUTE 'SELECT ' || vcurseur.attname || ' FROM ' || (vcurseur.attrelid)::regclass LOOP
RETURN NEXT;
END LOOP;
END LOOP;
END
$function$;
Il suffit ensuite d’une jointure entre cette fonction et la table pg_largeobject
:
SELECT oids.tableoid::regclass, sum(octet_length(data))
FROM lo_oids() oids
JOIN pg_largeobject ON (oids.loid = pg_largeobject.loid)
GROUP BY tableoid;
Cette solution est bien entendu facile à adapter, si besoin, pour sortir ces informations par colonne de table, par exemple.
Cependant, attention : les valeurs retournées sont les tailles des Large Objects, pas la place qu’ils occupent sur le disque.