web-dev-qa-db-ja.com

Postgresqlテーブルスペースに何があるかをどのように知ることができますか?

indexesという名前の新しいテーブルスペースを作成し、いくつかのテーブルとインデックスを含んでいた古いテーブルスペースindexes_oldを削除しようとしています。表領域を削除しようとすると、次のようになります。

=> drop tablespace indexes_old;
ERROR:  tablespace "indexes_old" is not empty

しかし、そこに何があるかを確認しようとすると、そのテーブルスペースにテーブルが存在しないようです。

=> 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)

それで、私がそれを落とすのを妨げているその表領域には何がありますか?

重要な場合は、pg_upgradeツールを使用してPg8.4からPg9.0に移行しました。

表領域は次のようになります。

    Name     |  Owner   |    Location     | Access privileges | Description 
-------------+----------+-----------------+-------------------+-------------
 indexes     | nobody   | /data/pgindex90 |                   | 
 indexes_old | nobody   | /data/pgindex84 |                   | 

/ data/pgindex84の内容には、すべての古い8.4インデックスに加えて、pg_upgradeが自動的に作成したこの新しい9.0インデックスが含まれます。

# 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
20
Andy Lester

Pg_classをチェックして、何がどこにあるかを確認します。

SELECT 
  c.relname, 
  t.spcname 
FROM 
  pg_class c 
    JOIN pg_tablespace t ON c.reltablespace = t.oid 
WHERE 
  t.spcname = 'indexes_old';
13
Frank Heikens

PostgreSQLでは、テーブルスペースは任意のPostgreSQLデータベースで使用できます。 (要求しているユーザーが十分な特権を持っている限り、つまり。)このクエリは

SELECT spcname, spclocation FROM pg_tablespace;

index_oldがPostgreSQLバージョンから9.1までのファイルシステムで使用しているディレクトリが表示されます。そこをうろついて、何か本物が邪魔になっていないか確認してください。ただし、PostgreSQLのインターフェースを使用する以外に、そこにあるものを削除しようとすることには本当に注意が必要です。

9.2+では、試してみてください

select spcname, pg_tablespace_location(oid) from pg_tablespace;

PG 10では、おそらく少し前に、これは次のように変化したようです。

SELECT tablename from pg_tables WHERE tablespace = 'foo';
3
Shorthand

残念ながら、すべてのデータベースに「グローバル」ビューがあります。ただし、これは dblink 拡張機能と次の関数を使用して実行できます。

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;

この関数は、現在のサーバー内のすべてのデータベースに有効なテーブルスペース名とユーザー名およびパスワードを受け入れます。

表領域名がnullとして渡された場合、デフォルトの表領域にないすべてのオブジェクトがリストされます(つまり、pg_global追加のテーブルスペースを使用しないデフォルトのインストール)

これは次のように使用できます。

select *
from show_tablespace_objects('indexes_old', 'postgres', 'verysecretpassword');