Listar colunas com índices no PostgreSQL

233

Gostaria de obter as colunas em que um índice está no PostgreSQL.

No MySQL você pode usar SHOW INDEXES FOR tablee olhar para a Column_namecoluna.

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      |         | 
+-------+------------+---------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+

Existe algo assim para o PostgreSQL?

Eu tentei \dno psqlprompt de comando (com a -Eopção de mostrar SQL), mas ele não mostra as informações que estou procurando.

Atualização: obrigado a todos que adicionaram suas respostas. cope360 me deu exatamente o que eu estava procurando, mas várias pessoas entraram em contato com links muito úteis. Para referência futura, consulte a documentação do pg_index (via Milen A. Radev ) e o artigo muito útil Extraindo informações META do PostgreSQL (via Michał Niklas ).

Luke Francl
fonte
Só para esclarecer: você deseja que seu programa seja capaz de descobrir, em tempo de execução, quais colunas são indexadas, certo? Ao contrário de você, o conhecimento de programação.
Wayne Conrad
Sim, correto. Idealmente, eu quero uma instrução SQL que lista apenas as colunas em que o índice está. Mas eu sei que o PostgreSQL é mais complicado que o MySQL e o índice pode estar em uma função etc.
Luke Francl

Respostas:

261

Crie alguns dados de teste ...

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

Listar índices e colunas indexados:

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

Enrole os nomes das colunas:

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
cope360
fonte
24
Para quem tenta encontrar índices em um banco de dados preenchido: essa consulta funciona muito bem, mas altere a and t.relname like 'test%'linha para a (s) tabela (s) desejada (s) ou apague essa linha completamente para encontrar todos os índices em seu banco de dados.
Erik J
1
Alguém poderia explicar o que relkind='r'significa?
Qwerty
5
@ Qwery, consulte a documentação para pg_class r = ordinary table, i = index, S = sequence, v = view, c = composite type, t = TOAST table.
precisa saber é o seguinte
1
existe uma maneira de também falar sobre a exclusividade da chave?
31316 Andrew
2
para ver a singularidade índice também seleccionarix.indisunique
Jana
177

PostgreSQL ( pg_indexes ):

SELECT * FROM pg_indexes WHERE tablename = 'mytable';

MySQL ( SHOW INDEX ):

SHOW INDEX FROM mytable;
Valentin Podkamennyi
fonte
3
Essa é a resposta mais direta e a mais interessante em termos de resposta à pergunta "Minha coluna está indexada?" PostgreSQL: SELECT COUNT(indexname) AS indexcount FROM pg_indexes WHERE tablename='mytablename' AND indexdef LIKE '%mycolumnname%' ;e verifique indexcount>0. mySQL: SHOW INDEX FROM mytablename WHERE Column_name='mycolumnname' ;e verifique se o conjunto de resultados não está vazio.
Zerobandwidth
2
Embora seja uma resposta muito útil em termos de recuperação de informações rápidas sobre índices, ela não responde à pergunta original porque a pg_indexesexibição não fornece nomes de colunas. postgresql.org/docs/current/view-pg-indexes.html
akagixxer
146

\d table_namemostra essas informações psql, mas se você deseja obter essas informações do banco de dados usando SQL, consulte Extrair informações do META do PostgreSQL .

Uso essas informações no meu utilitário para relatar algumas informações do esquema db para comparar os bancos de dados do PostgreSQL em ambientes de teste e produção.

Michał Niklas
fonte
Seu link para extrair meta informações do Postgres é exatamente o que eu estava procurando! Usando as dicas neste tópico e algumas escavações, cheguei bem perto da consulta que ele usa nesse post, mas é bom ter tudo organizado dessa maneira.
Luke Francl
1
Estou usando o AWS RDS PostgreSQL 9.6.5 e \d tablenão mostra nenhum índice; no entanto \di, mostra todos os índices.
Hendy Irawan
@HendyIrawan aparentemente pode ser afetado por outras configurações. Como eu me pergunto se você tinha o modo "somente tuplas" ativado (alternado por \t). Com "somente tuplas" ativada, não recebo índices de \d, com "somente tuplas" desativadas. Isso ocorre com o psql (PostgreSQL) 9.6.15.
JMM
77

Apenas faça: \d table_name

Mas não sei ao que você quer dizer que as informações sobre colunas não estão lá.

Por exemplo:

# \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)

Ele mostra claramente quais colunas cujo índice está nesta tabela.

shilovk
fonte
Eu estava esperando por algo que me permita fazer todos os índices em uma tabela, mas você está certo, \d index_nametem as informações. Para procurar os índices em uma tabela e depois os detalhes. Ao não mostrar as colunas, quero dizer que examinei o SQL gerado pelo \d tablenome e não é óbvio para mim de onde vem a lista de colunas. Eu acho que está sendo analisado fora da definição do índice, o que eu preferiria não fazer.
Luke Francl
Estou usando o AWS RDS PostgreSQL 9.6.5 e \d tablenão mostra nenhum índice; no entanto \di, mostra todos os índices.
Hendy Irawan
37

# \di

A maneira mais fácil e rápida é \di, que listará todos os índices no banco de dados atual.

$ \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é o "irmão pequeno" do \dcomando que irá listar todas as relações do atual d atabase. Assim \di, certamente, representam "me mostrar esta d atabases i ndexes".

A digitação \diSlistará todos os índices usados ​​em todo o sistema, o que significa que você obtém todos os índices pg_catalog também.

$ \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-- 

Com esses dois comandos, você pode adicionar um +depois para obter ainda mais informações, como o tamanho do espaço em disco que o índice precisa e uma descrição, se disponível.

$ \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)

No psql, você pode facilmente encontrar ajuda sobre a digitação de comandos \?.

sebisnow
fonte
2
Mas não mostra os nomes das colunas nas quais os índices são criados. O índice de chaves primárias compostas possui muitas colunas e essas não podem ser vistas.
Vignesh Raja
18

Combinado com outro código e criou uma visualização:

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;
naoko
fonte
12

Alguns dados de amostra ...

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

Use a pg_get_indexdeffunção:

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)
cope360
fonte
Simples e eficaz!
David
Simplesmente fantástico. Tenho sorte de ter rolado para esta resposta.
greatvovan
8

Este comando mostra a visualização de tabelas variáveis, índices e restrições também

=# \d table_name;

Exemplo:

testannie=# \d dv.l_customer_account;
Ariano
fonte
7

\d tablename mostra os nomes das colunas para mim na versão 8.3.8.

 "username_idx" UNIQUE, btree (username), tablespace "alldata1"
Corey
fonte
7

RESULTADO DA CONSULTA:

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)

INQUERIR:

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;
Dryymoon
fonte
agradável, no entanto, o nome da "coluna" para uma coluna é uma palavra reservada. IDEM para o esquema, deve usar column_name
parisni
5

As informações brutas estão em pg_index .

Milen A. Radev
fonte
Interessante. Especificamente indkey: "Esta é uma matriz de valores indnatts que indicam quais colunas da tabela esse índice indexa. Por exemplo, um valor 1 3 significaria que a primeira e a terceira colunas da tabela compõem a chave de índice. Um zero nessa matriz indica que o valor atributo de índice correspondente é uma expressão sobre as colunas da tabela, em vez de uma simples referência de coluna "
Luke Francl
2

Se você deseja preservar a ordem das colunas no índice, aqui está uma maneira (muito feia) de fazer isso:

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

a ordem das colunas é armazenada na coluna pg_index.indkey, então eu ordenei pelos subscritos dessa matriz.

David Willis
fonte
2

Ao brincar com índices, a ordem de quais colunas são construídas no índice é tão importante quanto as próprias colunas.

A consulta a seguir lista todos os índices para uma determinada tabela e todas as suas colunas de maneira classificada.

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
user6654165
fonte
2
Por que o OP "tenta fazer isso"? Uma boa resposta sempre terá uma explicação do que foi feito e por que foi feito dessa maneira, não apenas para o OP, mas também para futuros visitantes do SO que possam encontrar essa pergunta e estar lendo sua resposta.
Maximilian Ast
o ipara a ordinalidade é muito liso. Ele garante que as colunas sejam declaradas na ordem correta.
Kbrock
Esta foi a única resposta que funcionou para mim. A ordem das colunas é crítica. (Se você não acredita em mim, olhar para todas as pessoas com um primeiro nome Frank em uma agenda.)
Juraj
1

Tente a consulta abaixo para detalhar os índices necessários

Consulta como abaixo - eu tentei isso pessoalmente e use-o frequentemente.

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;
Barath Ravichander
fonte
1

Semelhante à resposta aceita, mas ter deixado join em pg_attribute como junção normal ou consulta com pg_attribute, não fornece índices que são como:
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;
Nikhil
fonte
boa nota, mas como obter informações sobre que "inferior (column_name")"
pleerock
1

Aqui está uma função que envolve a resposta do 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;

Uso:

select * from getIndices('<my_table>')
chribsen
fonte
Não listou partes dos meus índices que usam funções (por exemplo, "upper (field_name)").
precisa saber é o seguinte
0

Que tal uma solução simples:

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%'

`

Alex
fonte
Adoro esta solução. Infelizmente, ele falha com índices que possuem cláusulas where. (ou outro parêntese)
kbrock
Mudei para não pular parênteses no começo, e não capturá-las no meio, e largar tudo depois disso. '^[^\)]*\(([^\)]*)\).*$'
Kbrock
0

A excelente resposta de @ cope360, convertida para usar a sintaxe de junção.

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
;
Christian Long
fonte
0

Acho que essa versão ainda não existe neste segmento: fornece a lista de nomes de colunas e o ddl para o índice.

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;

Descobri que índices usando funções não vinculam a nomes de colunas; portanto, ocasionalmente, você encontra uma listagem de índices, por exemplo, um nome de coluna quando na verdade usa 3.

Exemplo:

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

A consulta retorna apenas 'col3' como uma coluna no índice, mas o DDL mostra o conjunto completo de colunas usadas no índice.

datico
fonte
0

Estenda a boa resposta de @ Cope360. Para obter uma determinada tabela (coloque o mesmo nome da tabela, mas esquema diferente), basta usar a tabela 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;

Explique: Eu tenho o nome da tabela 'tbassettype' no esquema 'dbAsset' e 'dbLegal'. Para obter apenas uma tabela no dbLegal, deixe a.attrelid = seu OID.

Wutikrai
fonte
0

Uma resposta um pouco modificada de @ 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;

Isso mostrará as colunas do índice na ordem correta:

index_name      is_unique  column_name
pk_test         true       c
pk_test         true       a
pk_test         true       b
Nikita Ryanov
fonte
O uso de "join esquerdo pg_attribute" também mostrará índices nas colunas computadas, é claro com um NULL column_name.
Paolo Bonzini 10/01/19
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)
Guy Cohen
fonte
0

A resposta aceita por @ cope360 é boa, mas eu queria algo um pouco mais como DBA_IND_COLUMNS da Oracle, ALL_IND_COLUMNS e USER_IND_COLUMNS (por exemplo, relata o esquema de tabela / índice e a posição do índice em um índice de várias colunas), então adaptei o responda a isso:

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
;

Isso fornece uma saída como:

 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)
Stephen
fonte