Comment puis-je savoir ce qu’il y a dans un tablespace Postgresql ?
-
12-11-2019 - |
Question
J'ai créé un nouveau tablespace appelé indexes
, et j'essaie de supprimer l'ancien tablespace indexes_old
, qui contenait des tables et des index.Lorsque j'essaie de supprimer le tablespace, j'obtiens :
=> drop tablespace indexes_old;
ERROR: tablespace "indexes_old" is not empty
Mais lorsque j'essaie de voir ce qu'il y a dedans, il semble qu'aucune table ne réside dans cet espace de table :
=> select * from pg_tables where tablespace = 'indexes_old';
schemaname | tablename | tableowner | tablespace | hasindexes | hasrules | hastriggers
------------+-----------+------------+------------+------------+----------+-------------
(0 rows)
=> select * from pg_indexes where tablespace = 'indexes_old';
schemaname | tablename | indexname | tablespace | indexdef
------------+-----------+-----------+------------+----------
(0 rows)
Alors, qu'y a-t-il dans cet espace de table qui m'empêche de le supprimer ?
Au cas où cela serait important, je viens de migrer de la page 8.4 vers la page 9.0 à l'aide de l'outil pg_upgrade.
Les tablespaces ressemblent à ceci :
Name | Owner | Location | Access privileges | Description
-------------+----------+-----------------+-------------------+-------------
indexes | nobody | /data/pgindex90 | |
indexes_old | nobody | /data/pgindex84 | |
et le contenu de /data/pgindex84 inclut tous les anciens index 8.4, plus ce nouvel index 9.0 créé automatiquement par pg_upgrade
# sudo ls -al /data/pgindex84/PG_9.0_201008051/11874
total 8280
drwx------ 2 postgres postgres 4096 Feb 9 14:58 .
drwx------ 3 postgres postgres 4096 Feb 11 09:28 ..
-rw------- 1 postgres postgres 40960 Feb 9 14:58 10462602
-rw------- 1 postgres postgres 40960 Feb 9 14:58 10462604
-rw------- 1 postgres postgres 4644864 Feb 9 14:58 10462614
-rw------- 1 postgres postgres 3727360 Feb 9 14:58 10462616
La solution
Vérifiez pg_class pour voir ce qui se trouve où :
SELECT
c.relname,
t.spcname
FROM
pg_class c
JOIN pg_tablespace t ON c.reltablespace = t.oid
WHERE
t.spcname = 'indexes_old';
Autres conseils
Dans PostgreSQL, un tablespace peut être utilisé par n'importe quelle base de données PostgreSQL.(Tant que l'utilisateur demandeur dispose de privilèges suffisants, bien sûr.) Je pense que cette requête
SELECT spcname, spclocation FROM pg_tablespace;
vous montrera le répertoire qu'index_old utilise dans le système de fichiers dans la version PostgreSQL jusqu'à 9.1.Rôdez là-dedans pour voir si quelque chose de réel vous gêne.Cependant, je serais très prudent avant d'essayer de supprimer quoi que ce soit en dehors de l'utilisation de l'interface de PostgreSQL.
Dans 9.2+, essayez
select spcname, pg_tablespace_location(oid) from pg_tablespace;
Dans PG 10 et peut-être un peu plus tôt, cela semble s'être transformé en :
SELECT tablename from pg_tables WHERE tablespace = 'foo';
Malheureusement, il existe une vue « globale » sur toutes les bases de données.Cependant, cela peut être fait en utilisant le clignoter extension avec la fonction suivante :
create or replace function show_tablespace_objects(p_tablespace text, p_user text, p_password text)
returns table (db_name text, schema_name text, object_name text, object_type text, tablespace_name text)
as
$func$
declare
l_stmt text;
l_con_name text := 'tbs_check_conn';
l_con_string text;
l_rec record;
begin
l_stmt := $query$SELECT current_database(),
n.nspname as schema_name,
c.relname as object_name,
case c.relkind
when 'r' then 'table'
when 'i' then 'index'
when 't' then 'TOAST table'
when 'm' then 'materialized view'
when 'f' then 'foreign table'
when 'p' then 'partitioned table'
else c.relkind::text
end as object_type,
t.spcname as tablespace_name
FROM pg_class c
JOIN pg_namespace n on n.oid = c.relnamespace
JOIN pg_tablespace t ON c.reltablespace = t.oid$query$;
if p_tablespace is not null then
l_stmt := l_stmt || format(' WHERE t.spcname=%L', p_tablespace);
end if;
for l_rec in (select * from pg_database where datallowconn) loop
l_con_string := format('dbname=%L user=%L password=%L',
l_rec.datname, p_user, p_password);
return query
select *
from dblink(l_con_string, l_stmt)
as t(db_name text, schema_name text, object_name text, object_type text, tablespace_name text);
end loop;
end;
$func$
language plpgsql;
La fonction accepte un nom d'espace table ainsi qu'un nom d'utilisateur et un mot de passe valides pour toutes les bases de données du serveur actuel.
Si le nom du tablespace est passé comme null
tous les objets qui ne sont pas dans le tablespace par défaut sont répertoriés (ce serait pg_global
dans une installation par défaut sans aucun tablespace supplémentaire)
Cela peut être utilisé comme ceci :
select *
from show_tablespace_objects('indexes_old', 'postgres', 'verysecretpassword');
Parlons-nous de l’interface PgSQL ?
Répertoriez les schémas (tablespaces) comme ceci :
\dn
Répertoriez toutes les tables d'un schéma (tablespace) comme ceci :
\dn <table_space>.*
Utiliser
\?
pour plus d'options