PostgreSQLでインデックス付きの列をリストする


233

PostgreSQLでインデックスが存在する列を取得したいと思います。

MySQL SHOW INDEXES FOR tableでは、Column_name列を使用して確認できます。

mysql> show indexes from foos;

+-------+------------+---------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name            | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------+------------+---------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| foos  |          0 | PRIMARY             |            1 | id          | A         |       19710 |     NULL | NULL   |      | BTREE      |         | 
| foos  |          0 | index_foos_on_email |            1 | email       | A         |       19710 |     NULL | NULL   | YES  | BTREE      |         | 
| foos  |          1 | index_foos_on_name  |            1 | name        | A         |       19710 |     NULL | NULL   |      | BTREE      |         | 
+-------+------------+---------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+

PostgreSQLにはこのようなものはありますか?

私はコマンドプロンプトで試し\dましたpsql-E SQLを表示オプション探している情報が表示されません。

更新:回答を追加してくれた皆さんに感謝します。cope360は私が探していたものを正確に提供してくれましたが、何人かの人々が非常に便利なリンクを提供してくれました。将来の参考のために、のためにドキュメントをチェックアウトPG_INDEX(経由Milen A.ラデフ)と非常に有用な製品のPostgreSQLから抽出META情報(経由のMichałニクラス)。


明確にするために:実行時に、どの列にインデックスが付けられているかをプログラムで把握できるようにしたいですか?あなたとは対照的にプログラミングの知識。
ウェインコンラッド

はい正解。理想的には、インデックスが存在する列のみをリストするSQLステートメントが必要です。しかし、PostgreSQLはMySQLよりも複雑で、インデックスが関数などにある可能性があることを知っています
Luke Francl

回答:


261

テストデータを作成...

create table test (a int, b int, c int, constraint pk_test primary key(a, b));
create table test2 (a int, b int, c int, constraint uk_test2 unique (b, c));
create table test3 (a int, b int, c int, constraint uk_test3b unique (b), constraint uk_test3c unique (c),constraint uk_test3ab unique (a, b));

インデックスとインデックス付きの列を一覧表示します。

select
    t.relname as table_name,
    i.relname as index_name,
    a.attname as column_name
from
    pg_class t,
    pg_class i,
    pg_index ix,
    pg_attribute a
where
    t.oid = ix.indrelid
    and i.oid = ix.indexrelid
    and a.attrelid = t.oid
    and a.attnum = ANY(ix.indkey)
    and t.relkind = 'r'
    and t.relname like 'test%'
order by
    t.relname,
    i.relname;

 table_name | index_name | column_name
------------+------------+-------------
 test       | pk_test    | a
 test       | pk_test    | b
 test2      | uk_test2   | b
 test2      | uk_test2   | c
 test3      | uk_test3ab | a
 test3      | uk_test3ab | b
 test3      | uk_test3b  | b
 test3      | uk_test3c  | c

列名をロールアップします。

select
    t.relname as table_name,
    i.relname as index_name,
    array_to_string(array_agg(a.attname), ', ') as column_names
from
    pg_class t,
    pg_class i,
    pg_index ix,
    pg_attribute a
where
    t.oid = ix.indrelid
    and i.oid = ix.indexrelid
    and a.attrelid = t.oid
    and a.attnum = ANY(ix.indkey)
    and t.relkind = 'r'
    and t.relname like 'test%'
group by
    t.relname,
    i.relname
order by
    t.relname,
    i.relname;

 table_name | index_name | column_names
------------+------------+--------------
 test       | pk_test    | a, b
 test2      | uk_test2   | b, c
 test3      | uk_test3ab | a, b
 test3      | uk_test3b  | b
 test3      | uk_test3c  | c

24
データが入力されたデータベースでインデックスを検索しようとする場合:このクエリはうまく機能しますが、and t.relname like 'test%'行を目的のテーブルに変更するか、その行を完全に消去して、データベース内のすべてのインデックスを検索します。
エリックJ

1
誰かがrelkind='r'意味を説明できますか?
Qwerty、2015年

5
@ Qwery、pg_classのドキュメントを参照してくださいr = ordinary table, i = index, S = sequence, v = view, c = composite type, t = TOAST table
cope360 2015年

1
キーの一意性についても伝える方法はありますか?
Andrew

2
インデックスの一意性も確認するには、選択してくださいix.indisunique
Jana

177

PostgreSQL(pg_indexes):

SELECT * FROM pg_indexes WHERE tablename = 'mytable';

MySQL(SHOW INDEX):

SHOW INDEX FROM mytable;

3
これは最も簡単な答えであり、「自分の列はインデックス付けされていますか?」という質問に答えるという点で最も興味深いものです。PostgreSQL:SELECT COUNT(indexname) AS indexcount FROM pg_indexes WHERE tablename='mytablename' AND indexdef LIKE '%mycolumnname%' ;確認しindexcount>0ます。mySQL:SHOW INDEX FROM mytablename WHERE Column_name='mycolumnname' ;結果セットが空でないことを確認します。
zerobandwidth

2
これは、インデックスに関する迅速な情報を取得するという点では非常に有用な回答ですが、pg_indexesビューには列名が表示されないため、元の質問には回答しません。postgresql.org/docs/current/view-pg-indexes.html
akagixxer '29 / 11/18

146

\d table_nameはこの情報をから示しpsqlていますが、SQLを使用してデータベースからそのような情報を取得する場合は、PostgreSQLからのMETA情報の抽出を参照してください。

ユーティリティでそのような情報を使用して、dbスキーマからいくつかの情報を報告し、テスト環境と本番環境でPostgreSQLデータベースを比較します。


Postgresからメタ情報を抽出するためのリンクは、まさに私が探していたものです。このスレッドのヒントといくつかの掘り下げを使用して、彼がその投稿で使用するクエリにかなり近づきましたが、すべてをそのようにレイアウトできるのは素晴らしいことです。
ルークフランクル

1
AWS RDS PostgreSQL 9.6.5を使用\d tableしていますが、インデックスは表示されませんが、\diすべてのインデックスが表示されます。
ヘンディイラワン2017

@HendyIrawan他の設定の影響を受ける可能性があります。あなたが「タプルのみ」モードをオンにしていたのかと思います(によって切り替えられます\t)。「タプルのみ」をオンにすると、からインデックスを取得でき\dません。「タプルのみ」をオフにすると、取得します。これは、psql(PostgreSQL)9.6.15の場合です。
JMM

77

ただやる: \d table_name

しかし、列に関する情報がそこにないのはどういう意味ですか。

例えば:

# \d pg_class
       Table "pg_catalog.pg_class"
     Column      |   Type    | Modifiers
-----------------+-----------+-----------
 relname         | name      | not null
 relnamespace    | oid       | not null
 reltype         | oid       | not null
 reloftype       | oid       | not null
 relowner        | oid       | not null
 relam           | oid       | not null
 relfilenode     | oid       | not null
 reltablespace   | oid       | not null
 relpages        | integer   | not null
 reltuples       | real      | not null
 reltoastrelid   | oid       | not null
 reltoastidxid   | oid       | not null
 relhasindex     | boolean   | not null
 relisshared     | boolean   | not null
 relistemp       | boolean   | not null
 relkind         | "char"    | not null
 relnatts        | smallint  | not null
 relchecks       | smallint  | not null
 relhasoids      | boolean   | not null
 relhaspkey      | boolean   | not null
 relhasexclusion | boolean   | not null
 relhasrules     | boolean   | not null
 relhastriggers  | boolean   | not null
 relhassubclass  | boolean   | not null
 relfrozenxid    | xid       | not null
 relacl          | aclitem[] |
 reloptions      | text[]    |
Indexes:
    "pg_class_oid_index" UNIQUE, btree (oid)
    "pg_class_relname_nsp_index" UNIQUE, btree (relname, relnamespace)

与えられたインデックスがこのテーブルにある列を明確に示します。


テーブルのすべてのインデックスを作成できる何かを望んでいましたが、そうです\d index_name、情報があります。そのため、テーブルのインデックスを調べてから、詳細を調べることができます。列を表示しない\d tableということは、名前で生成されたSQLを調べたことを意味し、列リストがどこから来ているのかがわかりません。インデックス定義から解析されていると思いますが、これは避けたいと思います。
ルークフランクル

AWS RDS PostgreSQL 9.6.5を使用\d tableしていますが、インデックスは表示されませんが、\diすべてのインデックスが表示されます。
ヘンディイラワン2017

37

# \di

簡単で最短の方法は\di、現在のデータベース内のすべてのインデックスを一覧表示するです。

$ \di
                      List of relations
 Schema |            Name             | Type  |  Owner   |     Table     
--------+-----------------------------+-------+----------+---------------
 public | part_delivery_index         | index | shipper  | part_delivery
 public | part_delivery_pkey          | index | shipper  | part_delivery
 public | shipment_by_mandator        | index | shipper  | shipment_info
 public | shipment_by_number_and_size | index | shipper  | shipment_info
 public | shipment_info_pkey          | index | shipper  | shipment_info
(5 rows)

\di「小さな兄弟」である\d現在のすべての関係を一覧表示するコマンドDの atabaseを。このように\di、確かに「この私を見るために立つdは atabases 私は ndexes」。

入力\diSすると、システム全体で使用されるすべてのインデックスが一覧表示されます。つまり、すべてのpg_catalogインデックスも取得できます。

$ \diS
                                      List of relations
   Schema   |                   Name                    | Type  |  Owner   |          Table
------------+-------------------------------------------+-------+----------+-------------------------
 pg_catalog | pg_aggregate_fnoid_index                  | index | postgres | pg_aggregate
 pg_catalog | pg_am_name_index                          | index | postgres | pg_am
 pg_catalog | pg_am_oid_index                           | index | postgres | pg_am
 pg_catalog | pg_amop_fam_strat_index                   | index | postgres | pg_amop
 pg_catalog | pg_amop_oid_index                         | index | postgres | pg_amop
 pg_catalog | pg_amop_opr_fam_index                     | index | postgres | pg_amop
 pg_catalog | pg_amproc_fam_proc_index                  | index | postgres | pg_amproc
 pg_catalog | pg_amproc_oid_index                       | index | postgres | pg_amproc
 pg_catalog | pg_attrdef_adrelid_adnum_index            | index | postgres | pg_attrdef
--More-- 

これらの両方のコマンドを使用すると、+後にを追加して、インデックスに必要なディスクスペースのサイズや、可能な場合は説明など、さらに多くの情報を取得できます。

$ \di+
                                 List of relations
 Schema |            Name             | Type  |  Owner   |     Table     | Size  | Description 
--------+-----------------------------+-------+----------+---------------+-------+-------------
 public | part_delivery_index         | index | shipper  | part_delivery | 16 kB | 
 public | part_delivery_pkey          | index | shipper  | part_delivery | 16 kB | 
 public | shipment_by_mandator        | index | shipper  | shipment_info | 19 MB | 
 public | shipment_by_number_and_size | index | shipper  | shipment_info | 19 MB | 
 public | shipment_info_pkey          | index | shipper  | shipment_info | 53 MB | 
(5 rows)

psqlでは、コマンドの入力に関するヘルプを簡単に見つけることができます\?


2
ただし、インデックスが作成された列の名前は表示されません。複合主キーインデックスには多くの列があり、それらは表示されません。
Vignesh Raja 2018

18

他のコードと組み合わせてビューを作成しました:

CREATE OR REPLACE VIEW view_index AS 
SELECT
     n.nspname  as "schema"
    ,t.relname  as "table"
    ,c.relname  as "index"
    ,pg_get_indexdef(indexrelid) as "def"
FROM pg_catalog.pg_class c
    JOIN pg_catalog.pg_namespace n ON n.oid        = c.relnamespace
    JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid
    JOIN pg_catalog.pg_class t ON i.indrelid   = t.oid
WHERE c.relkind = 'i'
    and n.nspname not in ('pg_catalog', 'pg_toast')
    and pg_catalog.pg_table_is_visible(c.oid)
ORDER BY
     n.nspname
    ,t.relname
    ,c.relname;

12

いくつかのサンプルデータ...

create table test (a int, b int, c int, constraint pk_test primary key(a, b));
create table test2 (a int, b int, c int, constraint uk_test2 unique (b, c));
create table test3 (a int, b int, c int, constraint uk_test3b unique (b), constraint uk_test3c unique (c), constraint uk_test3ab unique (a, b));

pg_get_indexdef関数を使用:

select pg_get_indexdef(indexrelid) from pg_index where indrelid = 'test'::regclass;

                    pg_get_indexdef
--------------------------------------------------------
 CREATE UNIQUE INDEX pk_test ON test USING btree (a, b)
(1 row)


select pg_get_indexdef(indexrelid) from pg_index where indrelid = 'test2'::regclass;
                     pg_get_indexdef
----------------------------------------------------------
 CREATE UNIQUE INDEX uk_test2 ON test2 USING btree (b, c)
(1 row)


select pg_get_indexdef(indexrelid) from pg_index where indrelid ='test3'::regclass;
                      pg_get_indexdef
------------------------------------------------------------
 CREATE UNIQUE INDEX uk_test3b ON test3 USING btree (b)
 CREATE UNIQUE INDEX uk_test3c ON test3 USING btree (c)
 CREATE UNIQUE INDEX uk_test3ab ON test3 USING btree (a, b)
(3 rows)

シンプルで効果的!
デビッド

すごい。私はこの答えにスクロールできて幸運です。
greatvovan 2018

8

このコマンドは、テーブル変数、インデックス、制約のビューも表示します

=# \d table_name;

例:

testannie=# \d dv.l_customer_account;

7

\d tablename は、バージョン8.3.8での私の列名を示しています。

 "username_idx" UNIQUE, btree (username), tablespace "alldata1"

7

クエリの結果:

table |     column     |          type          | notnull |  index_name  | is_index | primarykey | uniquekey | default
-------+----------------+------------------------+---------+--------------+----------+-   -----------+-----------+---------
 nodes | dns_datacenter | character varying(255) | f       |              | f        | f          | f         |
 nodes | dns_name       | character varying(255) | f       | dns_name_idx | t        | f          | f         |
 nodes | id             | uuid                   | t       | nodes_pkey   | t        | t          | t         |
(3 rows)

クエリ:

SELECT  
c.relname AS table,
f.attname AS column,  
pg_catalog.format_type(f.atttypid,f.atttypmod) AS type,
f.attnotnull AS notnull,  
i.relname as index_name,
CASE  
    WHEN i.oid<>0 THEN 't'  
    ELSE 'f'  
END AS is_index,  
CASE  
    WHEN p.contype = 'p' THEN 't'  
    ELSE 'f'  
END AS primarykey,  
CASE  
    WHEN p.contype = 'u' THEN 't' 
    WHEN p.contype = 'p' THEN 't' 
    ELSE 'f'
END AS uniquekey,
CASE
    WHEN f.atthasdef = 't' THEN d.adsrc
END AS default  FROM pg_attribute f  
JOIN pg_class c ON c.oid = f.attrelid  
JOIN pg_type t ON t.oid = f.atttypid  
LEFT JOIN pg_attrdef d ON d.adrelid = c.oid AND d.adnum = f.attnum  
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace  
LEFT JOIN pg_constraint p ON p.conrelid = c.oid AND f.attnum = ANY (p.conkey)  
LEFT JOIN pg_class AS g ON p.confrelid = g.oid
LEFT JOIN pg_index AS ix ON f.attnum = ANY(ix.indkey) and c.oid = f.attrelid and c.oid = ix.indrelid 
LEFT JOIN pg_class AS i ON ix.indexrelid = i.oid 

WHERE c.relkind = 'r'::char  
AND n.nspname = 'public'  -- Replace with Schema name 
--AND c.relname = 'nodes'  -- Replace with table name, or Comment this for get all tables
AND f.attnum > 0
ORDER BY c.relname,f.attname;

いいのですが、列の「列」名は予約語です。スキーマの
IDEM

5

生の情報はpg_indexにあります。


面白い。具体的にindkeyは、次のとおりです。「これは、インデックスがインデックスを作成するテーブルカラムを示すindnatts値の配列です。たとえば、1 3の値は、最初と3番目のテーブルカラムがインデックスキーを構成することを意味します。この配列のゼロは、対応するインデックス属性は、単純な列参照ではなく、テーブル列に対する式です。」
Luke Francl

2

インデックスの列の順序を維持したい場合は、次の方法で(非常に醜い)方法を実行します。

select table_name,
    index_name,
    array_agg(column_name)
from (
    select
        t.relname as table_name,
        i.relname as index_name,
        a.attname as column_name,
        unnest(ix.indkey) as unn,
        a.attnum
    from
        pg_class t,
        pg_class i,
        pg_index ix,
        pg_attribute a
    where
        t.oid = ix.indrelid
        and i.oid = ix.indexrelid
        and a.attrelid = t.oid
        and a.attnum = ANY(ix.indkey)
        and t.relkind = 'r'
        and t.relnamespace = <oid of the schema you're interested in>
    order by
        t.relname,
        i.relname,
        generate_subscripts(ix.indkey,1)) sb
where unn = attnum
group by table_name, index_name

列の順序はpg_index.indkey列に格納されるので、その配列の添え字で順序付けしました。


2

インデックスをいじるとき、インデックスで構築される列の順序は、列自体と同じくらい重要です。

次のクエリは、指定されたテーブルのすべてのインデックスとそのすべての列を並べ替えて一覧表示します。

SELECT
  table_name,
  index_name,
  string_agg(column_name, ',')
FROM (
       SELECT
         t.relname AS table_name,
         i.relname AS index_name,
         a.attname AS column_name,
         (SELECT i
          FROM (SELECT
                  *,
                  row_number()
                  OVER () i
                FROM unnest(indkey) WITH ORDINALITY AS a(v)) a
          WHERE v = attnum)
       FROM
         pg_class t,
         pg_class i,
         pg_index ix,
         pg_attribute a
       WHERE
         t.oid = ix.indrelid
         AND i.oid = ix.indexrelid
         AND a.attrelid = t.oid
         AND a.attnum = ANY (ix.indkey)
         AND t.relkind = 'r'
         AND t.relname LIKE 'tablename'
       ORDER BY table_name, index_name, i
     ) raw
GROUP BY table_name, index_name

2
OPが「これを試す」必要があるのはなぜですか?良い答えは常に行われていたもの、それはOPのためではなく、この質問を見つけることができますし、あなたの答えを読んだことがSOに将来の訪問者のためだけではなく、そのように行われていた理由の説明があります。
Maximilian Ast

i規則性のためには、非常に滑らかなです。列が正しい順序で記述されていることを確認します。
kbrock

これが私にとってうまくいった唯一の答えでした。列の順序は重要です。(私を信じていない場合は、電話帳で名前がフランクのすべての人を探してください。)
Juraj

1

必要なインデックスにドリルダウンするには、以下のクエリを試してください

以下のクエリ-私はこれを個人的に試し、頻繁に使用しています。

SELECT n.nspname as "Schema",
  c.relname as "Name",
  CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'i' 
THEN 'index' WHEN 'S' THEN 'sequence' WHEN 's' THEN 'special' END as "Type",
  u.usename as "Owner",
 c2.relname as "Table"
FROM pg_catalog.pg_class c
     JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid
     JOIN pg_catalog.pg_class c2 ON i.indrelid = c2.oid
     LEFT JOIN pg_catalog.pg_user u ON u.usesysid = c.relowner
     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind IN ('i','')
      AND n.nspname NOT IN ('pg_catalog', 'pg_toast')
      AND pg_catalog.pg_table_is_visible(c.oid)
      AND c2.relname like '%agg_transaction%' --table name
      AND nspname = 'edjus' -- schema name 
ORDER BY 1,2;

1

受け入れ答えに似ていますが、ある参加左のpg_attributeに参加正常またはクエリとしてのpg_attributeのようなもののdoesntの所与のインデックス:
create unique index unique_user_name_index on users (lower(name))

select 
    row_number() over (order by c.relname),
    c.relname as index, 
    t.relname as table, 
    array_to_string(array_agg(a.attname), ', ') as column_names 
from pg_class c
join pg_index i on c.oid = i.indexrelid and c.relkind='i' and c.relname not like 'pg_%' 
join pg_class t on t.oid = i.indrelid
left join pg_attribute a on a.attrelid = t.oid and a.attnum = ANY(i.indkey) 
group by t.relname, c.relname order by c.relname;

良いメモですが、その "lower(column_name") "に関する情報を取得する方法
pleerock

1

cope360の答えをラップする関数は次のとおりです。

CREATE OR REPLACE FUNCTION getIndices(_table_name varchar)
  RETURNS TABLE(table_name varchar, index_name varchar, column_name varchar) AS $$
  BEGIN
    RETURN QUERY
    select
    t.relname::varchar as table_name,
    i.relname::varchar as index_name,
    a.attname::varchar as column_name
from
    pg_class t,
    pg_class i,
    pg_index ix,
    pg_attribute a
where
    t.oid = ix.indrelid
    and i.oid = ix.indexrelid
    and a.attrelid = t.oid
    and a.attnum = ANY(ix.indkey)
    and t.relkind = 'r'
    and t.relname = _table_name
order by
    t.relname,
    i.relname;
  END;
  $$ LANGUAGE plpgsql;

使用法:

select * from getIndices('<my_table>')

関数を使用するインデックスの一部をリストしませんでした(例: "upper(field_name)")。
JohnMudd 2017年

0

簡単な解決策はどうですか:

SELECT 
  t.relname table_name,
  ix.relname index_name,
  indisunique,
  indisprimary, 
  regexp_replace(pg_get_indexdef(indexrelid), '.*\((.*)\)', '\1') columns
FROM pg_index i
JOIN pg_class t ON t.oid = i.indrelid
JOIN pg_class ix ON ix.oid = i.indexrelid
WHERE t.relname LIKE 'test%'

`


このソリューションが大好きです。残念ながら、where句のあるインデックスでは失敗します。(または他の括弧)
kbrock 2018

最初は括弧をスキップせず、途中で括弧をキャプチャせず、その後すべてをドロップするように変更しました。'^[^\)]*\(([^\)]*)\).*$'
kbrock 2018

0

@ cope360の優れた回答。結合構文を使用するように変換されます。

select t.relname as table_name
     , i.relname as index_name
     , array_to_string(array_agg(a.attname), ', ') as column_names
from pg_class t
join pg_index ix
on t.oid = ix.indrelid
join pg_class i
on i.oid = ix.indexrelid
join pg_attribute a
on a.attrelid = t.oid
and a.attnum = ANY(ix.indkey)
where t.relkind = 'r'
and t.relname like 'test%'
group by t.relname
       , i.relname
order by t.relname
       , i.relname
;

0

このバージョンはまだこのスレッドには存在しないと思います。列名のリストとインデックスのddlの両方を提供します。

CREATE OR REPLACE VIEW V_TABLE_INDEXES AS

SELECT
     n.nspname  as "schema"
    ,t.relname  as "table"
    ,c.relname  as "index"
    ,i.indisunique AS "is_unique"
    ,array_to_string(array_agg(a.attname), ', ') as "columns"
    ,pg_get_indexdef(i.indexrelid) as "ddl"
FROM pg_catalog.pg_class c
    JOIN pg_catalog.pg_namespace n ON n.oid        = c.relnamespace
    JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid
    JOIN pg_catalog.pg_class t ON i.indrelid   = t.oid
    JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(i.indkey)
WHERE c.relkind = 'i'
      and n.nspname not in ('pg_catalog', 'pg_toast')
      and pg_catalog.pg_table_is_visible(c.oid)
GROUP BY
    n.nspname
    ,t.relname
    ,c.relname
    ,i.indisunique
    ,i.indexrelid
ORDER BY
    n.nspname
    ,t.relname
    ,c.relname;

関数を使用するインデックスは列名にリンクしていないことがわかりました。そのため、実際にはが使用されているときに、1つの列名などのインデックスリストが時々見つかります。

例:

CREATE INDEX ui1 ON table1 (coalesce(col1,''),coalesce(col2,''),col3)

クエリは 'col3'のみをインデックスの列として返しますが、DDLはインデックスで使用される列の完全なセットを示します。


0

@ Cope360の適切な回答に拡張してください。特定のテーブルを取得するには(テーブル名が同じでスキーマが異なる場合)、テーブルOIDを使用します。

select
     t.relname as table_name
    ,i.relname as index_name
    ,a.attname as column_name
    ,a.attrelid tableid

from
    pg_class t,
    pg_class i,
    pg_index ix,
    pg_attribute a
where
    t.oid = ix.indrelid
    and i.oid = ix.indexrelid
    and a.attrelid = t.oid
    and a.attnum = ANY(ix.indkey)
    and t.relkind = 'r'
    -- and t.relname like 'tbassettype'
    and a.attrelid = '"dbLegal".tbassettype'::regclass
order by
    t.relname,
    i.relname;

説明:スキーマ「dbAsset」と「dbLegal」の両方にテーブル名「tbassettype」があります。dbLegalのテーブルのみを取得するには、a.attrelid =そのOIDを指定します。


0

@ cope360の少し修正された答え:

create table test (a int, b int, c int, constraint pk_test primary key(c, a, b));
select i.relname as index_name,
       ix.indisunique as is_unique,
       a.attname as column_name,
from pg_class c
       inner join pg_index ix on c.oid=ix.indrelid
       inner join pg_class i on ix.indexrelid=i.oid
       inner join pg_attribute a on a.attrelid=c.oid and a.attnum=any(ix.indkey)
where c.oid='public.test'::regclass::oid
order by array_position(ix.indkey, a.attnum) asc;

これにより、インデックス列が正しい順序で表示されます。

index_name      is_unique  column_name
pk_test         true       c
pk_test         true       a
pk_test         true       b

「左結合pg_attribute」を使用すると、もちろんNULLのcolumn_nameを持つ計算列のインデックスも表示されます。
Paolo Bonzini、

0
select t.relname as table_name, 
       i.relname as index_name, 
       array_position(ix.indkey,a.attnum) pos, 
       a.attname as column_name
from pg_class t
join pg_index ix on t.oid = ix.indrelid
join pg_class i on i.oid = ix.indexrelid
join pg_attribute a on a.attrelid = t.oid and a.attnum = ANY(ix.indkey)
where t.relkind = 'r'
and t.relname like 'orders'
order by t.relname, i.relname, array_position(ix.indkey,a.attnum)

0

@ cope360による承認された回答は良いですが、OracleのDBA_IND_COLUMNS、ALL_IND_COLUMNS、およびUSER_IND_COLUMNS(たとえば、テーブル/インデックススキーマと複数列インデックス内のインデックスの位置を報告する)のようなものが少し欲しかったため、承認されたこれに答える:

with
 ind_cols as (
select
    n.nspname as schema_name,
    t.relname as table_name,
    i.relname as index_name,
    a.attname as column_name,
    1 + array_position(ix.indkey, a.attnum) as column_position
from
     pg_catalog.pg_class t
join pg_catalog.pg_attribute a on t.oid    =      a.attrelid 
join pg_catalog.pg_index ix    on t.oid    =     ix.indrelid
join pg_catalog.pg_class i     on a.attnum = any(ix.indkey)
                              and i.oid    =     ix.indexrelid
join pg_catalog.pg_namespace n on n.oid    =      t.relnamespace
where t.relkind = 'r'
order by
    t.relname,
    i.relname,
    array_position(ix.indkey, a.attnum)
)
select * 
from ind_cols
where schema_name = 'test'
  and table_name  = 'indextest'
order by schema_name, table_name
;

これにより、次のような出力が得られます。

 schema_name | table_name | index_name | column_name | column_position 
-------------+------------+------------+-------------+-----------------
 test        | indextest  | testind1   | singleindex |               1
 test        | indextest  | testind2   | firstoftwo  |               1
 test        | indextest  | testind2   | secondoftwo |               2
(3 rows)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.