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합니다 (로 프롬프트 명령 -ESQL을 표시하는 옵션)하지만 내가 찾는 정보를 표시하지 않습니다.

업데이트 : 답변을 추가 한 모든 사람에게 감사합니다. cope360 은 내가 찾던 것을 정확히 줬지만 여러 사람들이 매우 유용한 링크로 차임했습니다. 미래 참고로, 설명서 확인 PG_INDEX (를 통해 Milen A. Radev )과 매우 유용한 기사 의 PostgreSQL에서 추출 메타 정보 (통해 마이클 니클라스을 ).


명확히하기 위해 : 런타임에 어떤 열이 색인화되는지 프로그램이 알아낼 수 있기를 원합니까? 당신과는 달리 프로그래밍 지식.
Wayne Conrad

네 맞습니다. 이상적으로는 인덱스가있는 열만 나열하는 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%'행을 원하는 테이블로 변경 하거나 해당 행을 완전히 지워서 DB에서 모든 인덱스를 찾으십시오.
Erik J

1
누군가가 무슨 relkind='r'의미 인지 설명 할 수 있습니까?
Qwerty

5
@Qwery, pg_class 문서를 참조하십시오 r = ordinary table, i = index, S = sequence, v = view, c = composite type, t = TOAST table.
cope360

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%' ;및 verify indexcount>0. mySQL : SHOW INDEX FROM mytablename WHERE Column_name='mycolumnname' ;및 결과 세트가 비어 있지 않은지 확인하십시오.
zerobandwidth

2
이것은 인덱스에 대한 빠른 정보를 검색하는 데있어 매우 유용한 답변이지만 pg_indexes보기에 열 이름을 제공하지 않기 때문에 원래 질문에 대답 하지 않습니다. postgresql.org/docs/current/view-pg-indexes.html
akagixxer

146

\d table_name에서이 정보를 보여 psql주지만 SQL을 사용하여 데이터베이스에서 이러한 정보를 얻으려면 PostgreSQL에서 META 정보 추출을 살펴보십시오 .

유틸리티 에서 이러한 정보를 사용 하여 테스트 및 프로덕션 환경에서 PostgreSQL 데이터베이스를 비교하기 위해 db 스키마의 일부 정보를보고 합니다.


Postgres에서 메타 정보를 추출하는 링크는 내가 찾던 것입니다! 이 스레드의 팁과 일부 파기를 사용하여 해당 게시물에서 사용하는 쿼리에 매우 가까워졌지만 모두 그렇게 배치하는 것이 좋습니다.
Luke Francl

1
AWS RDS PostgreSQL 9.6.5를 사용하고 \d table있으며 인덱스를 표시하지 않지만 \di모든 인덱스를 표시합니다.
Hendy Irawan

@HendyIrawan 다른 설정의 영향을받을 수 있습니다. "tuples only"모드가 켜져 있는지 궁금합니다 \t. "tuples only"를 설정하면 "tuples only"를 \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을 보았고 열 목록이 어디에서 왔는지 명확하지 않습니다. 인덱스 정의에서 파싱되고 있다고 생각합니다.
Luke Francl

AWS RDS PostgreSQL 9.6.5를 사용하고 \d table있으며 인덱스를 표시하지 않지만 \di모든 인덱스를 표시합니다.
Hendy Irawan

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는 이 터 베 내가 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

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)

간단하고 효과적입니다!
David

대단해 이 답변으로 스크롤하여 운이 좋았습니다.
greatvovan

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은, COLUMN_NAME 사용해야합니다
parisni

5

원시 정보는 pg_index에 있습니다.


흥미 롭군 구체적으로 indkey: "이 인덱스가 인덱스하는 테이블 열을 나타내는 indnatts 값의 배열입니다. 예를 들어 값 1 3은 첫 번째 테이블 테이블과 세 번째 테이블 열이 인덱스 키를 구성 함을 의미합니다.이 배열에서 0은 해당 인덱스 속성은 단순한 열 참조가 아니라 테이블 열에 대한 표현식입니다. "
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는 왜 "이것을 시도해야합니까?" 좋은 대답은 항상 일이 있었는지에 대한 설명을 것이다가 영업을 위해하지만이 질문을 찾을 수 있으며, 답변을 읽을 수 SO 미래의 방문자뿐만 아니라, 그런 식으로 일을 한 이유.
막시밀리안 Ast

i순서와에 대한 매우 매끄러운입니다. 열이 올바른 순서로 표시되도록합니다.
kbrock

이것은 나를 위해 일한 유일한 대답이었습니다. 열 순서가 중요합니다. (당신이 나를 믿지 않는다면, 전화 번호부에서 Frank라는 이름을 가진 모든 사람들을 찾으십시오.)
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에 조인남겨 두거나 pg_attribute를 사용하여 쿼리하면 다음과 같은 색인을 제공하지 않습니다.
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

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

처음에는 파렌을 건너 뛰지 않고 중간에 파렌을 캡처하지 않고 그 후에 모든 것을 떨어 뜨 렸습니다. '^[^\)]*\(([^\)]*)\).*$'
kbrock

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;

함수를 사용하는 인덱스는 열 이름에 연결되지 않으므로 때때로 3을 사용하는 경우 하나의 열 이름과 같은 인덱스 목록을 찾을 수 있습니다.

예:

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 2019 년

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.