Lista de columnas con índices en PostgreSQL

233

Me gustaría obtener las columnas en las que se encuentra un índice en PostgreSQL.

En MySQL puede usar SHOW INDEXES FOR tabley mirar la Column_namecolumna.

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 como esto para PostgreSQL?

He intentado \den el psqlsímbolo del sistema (con la -Eopción de mostrar SQL) pero no muestra la información que estoy buscando.

Actualización: Gracias a todos los que agregaron sus respuestas. cope360 me dio exactamente lo que estaba buscando, pero varias personas intervinieron con enlaces muy útiles. Para referencia futura, consulte la documentación de pg_index (a través de Milen A. Radev ) y el muy útil artículo Extracción de información META de PostgreSQL (a través de Michał Niklas ).

Luke Francl
fuente
Solo para aclarar: desea que su programa pueda descubrir, en tiempo de ejecución, qué columnas están indexadas, ¿verdad? A diferencia de ti, la programación sabe.
Wayne Conrad
Sí correcto. Idealmente, quiero una declaración SQL que enumere SOLO las columnas en las que se encuentra el índice. Pero sé que PostgreSQL es más complicado que MySQL y el índice podría estar en una función, etc.
Luke Francl

Respuestas:

261

Crea algunos datos de prueba ...

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

Lista de índices y columnas indexadas:

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

Enrollar los nombres de columna:

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
fuente
24
Para cualquiera que intente encontrar índices en una base de datos poblada: esta consulta funciona muy bien, pero cambie la and t.relname like 'test%'línea a la (s) tabla (s) que desee o borre esa línea por completo para encontrar todos los índices en su base de datos.
Erik J
1
¿Alguien podría explicar qué relkind='r'significa?
Qwerty
55
@Qwery, consulte la documentación de pg_class r = ordinary table, i = index, S = sequence, v = view, c = composite type, t = TOAST table.
cope360
1
¿hay alguna manera de contar también sobre la unicidad de la clave?
Andrew
2
para ver la unicidad del índice también seleccioneix.indisunique
Jana
177

PostgreSQL ( pg_indexes ):

SELECT * FROM pg_indexes WHERE tablename = 'mytable';

MySQL ( MOSTRAR ÍNDICE ):

SHOW INDEX FROM mytable;
Valentin Podkamennyi
fuente
3
Esta es la respuesta más directa y la más interesante en términos de responder la pregunta "¿Está indexada mi columna?" PostgreSQL: SELECT COUNT(indexname) AS indexcount FROM pg_indexes WHERE tablename='mytablename' AND indexdef LIKE '%mycolumnname%' ;y verificar indexcount>0. mySQL: SHOW INDEX FROM mytablename WHERE Column_name='mycolumnname' ;y verifique que el conjunto de resultados no esté vacío.
zerobandwidth
2
Aunque esta es una respuesta muy útil en términos de recuperación de información rápida sobre índices, no responde la pregunta original porque la pg_indexesvista no proporciona nombres de columna. postgresql.org/docs/current/view-pg-indexes.html
akagixxer
146

\d table_namemuestra esta información psql, pero si desea obtener dicha información de la base de datos utilizando SQL, eche un vistazo a Extracción de información META de PostgreSQL .

Utilizo dicha información en mi utilidad para informar cierta información del esquema db para comparar bases de datos PostgreSQL en entornos de prueba y producción.

Michał Niklas
fuente
¡Su enlace para extraer metainformación de Postgres es exactamente lo que estaba buscando! Utilizando los consejos en este hilo y cavando, me acerqué bastante a la consulta que usa en esa publicación, pero es bueno tenerlo todo así.
Luke Francl
1
Estoy usando AWS RDS PostgreSQL 9.6.5 y \d tableno muestra ningún índice, sin embargo \di, muestra todos los índices.
Hendy Irawan
@HendyIrawan aparentemente puede verse afectado por otras configuraciones. Como me pregunto si tenías el modo "solo tuplas" activado (activado \t). Con "solo \dtuplas" activado, no obtengo índices , con "solo tuplas" desactivado, sí. Esto es con psql (PostgreSQL) 9.6.15.
JMM
77

Solo haz: \d table_name

Pero no estoy seguro de qué quiere decir que la información sobre las columnas no está allí.

Por ejemplo:

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

Muestra claramente qué columnas da el índice está en esta tabla.

shilovk
fuente
Esperaba algo que me permitiera hacer todos los índices en una tabla, pero tienes razón, \d index_nametiene la información. Entonces puedo buscar los índices en una tabla y luego buscar los detalles. Al no mostrar las columnas quiero decir que miré el SQL generado por \d tablenombre y no es obvio para mí de dónde proviene la lista de columnas. Creo que se está analizando a partir de la definición del índice, que preferiría no hacer.
Luke Francl
Estoy usando AWS RDS PostgreSQL 9.6.5 y \d tableno muestra ningún índice, sin embargo \di, muestra todos los índices.
Hendy Irawan
37

# \di

La forma más fácil y más corta es \di, que enumerará todos los índices en la base de datos actual.

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

\dies el "hermano pequeño" del \dcomando que enumerará todas las relaciones de la corriente d atabase. Por lo tanto \di, sin duda significar "a mostrar este d atabases i ndexes".

Al escribir, \diSse enumerarán todos los índices utilizados en todo el sistema, lo que significa que también obtendrá todos los índices 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-- 

Con estos dos comandos, puede agregar un +después para obtener aún más información, como el tamaño del espacio en disco que necesita el índice y una descripción si está disponible.

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

En psql puede encontrar fácilmente ayuda sobre la escritura de comandos \?.

sebisnow
fuente
2
Pero no muestra los nombres de columna en los que se crean los índices. El índice de claves primarias compuestas tiene muchas columnas y no se pueden ver.
Vignesh Raja
18

En combinación con el código de otros y creó una vista:

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
fuente
12

Algunos datos de muestra ...

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

Utilizar la pg_get_indexdeffunción:

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
fuente
Simple y efectivo!
David
Simplemente impresionante. Tengo suerte de que me haya desplazado a esta respuesta.
greatvovan
8

Este comando también muestra la vista de las variables, índices y restricciones de las tablas.

=# \d table_name;

Ejemplo:

testannie=# \d dv.l_customer_account;
ario
fuente
7

\d tablename me muestra los nombres de columna en la versión 8.3.8.

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

RESULTADO DE LA 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)

CONSULTA:

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
fuente
agradable, sin embargo, el nombre de "columna" para una columna es una palabra reservada. IDEM para el esquema, debe usar
column_name
5

La información en bruto está en pg_index .

Milen A. Radev
fuente
Interesante. Específicamente indkey: "Esta es una matriz de valores indnatts que indican qué columnas de la tabla indexa este índice. Por ejemplo, un valor de 1 3 significaría que la primera y la tercera columna de la tabla constituyen la clave del índice. Un cero en esta matriz indica que El atributo de índice correspondiente es una expresión sobre las columnas de la tabla, en lugar de una simple referencia de columna "
Luke Francl
2

Si desea preservar el orden de las columnas en el índice, aquí hay una forma (muy fea) de hacerlo:

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

El orden de las columnas se almacena en la columna pg_index.indkey, por lo que ordené por los subíndices de esa matriz.

David Willis
fuente
2

Cuando se juega con índices, el orden de las columnas que se construyen en el índice es tan importante como las columnas mismas.

La siguiente consulta enumera todos los índices de una tabla determinada y todas sus columnas de forma ordenada.

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
usuario6654165
fuente
2
¿Por qué debería el OP "probar esto"? Una buena respuesta siempre tendrá una explicación de lo que se hizo y por qué se hizo de esa manera, no solo para el OP sino para los futuros visitantes de SO que pueden encontrar esta pregunta y leer su respuesta.
Maximilian Ast
el ipara la ordinalidad es muy hábil. Asegura que las columnas se indiquen en el orden correcto.
kbrock
Esta fue la única respuesta que me funcionó. El orden de las columnas es crítico. (Si no me cree, busque a todas las personas con un nombre de pila Frank en una agenda telefónica)
Juraj
1

Intente la consulta a continuación para profundizar en los índices necesarios

Consulta de la siguiente manera: lo he intentado personalmente y lo uso con frecuencia.

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
fuente
1

Similar a la respuesta aceptada, pero haber dejado unirse en pg_attribute como combinación normal o consulta con pg_attribute no da índices que sean 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
fuente
buena nota, pero cómo obtener información sobre ese "menor (nombre_columna") "
pleerock
1

Aquí hay una función que envuelve la respuesta de 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
fuente
No enumeré partes de mis índices que usan funciones (por ejemplo, "upper (field_name)").
JohnMudd
0

¿Qué tal una solución simple:

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
fuente
Amo esta solución. Desafortunadamente falla con índices que tienen cláusulas where. (u otro paréntesis)
kbrock
Cambié para no omitir parens al principio, y no capturar parens en el medio, y dejar todo después de eso. '^[^\)]*\(([^\)]*)\).*$'
kbrock
0

La excelente respuesta de @ cope360, convertida para usar la sintaxis de unión.

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
;
Cristiano largo
fuente
0

Todavía no creo que esta versión exista en este hilo: proporciona la lista de nombres de columna junto con el ddl para el í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;

Descubrí que los índices que usan funciones no se vinculan con los nombres de las columnas, por lo que ocasionalmente puede encontrar una lista de índices, por ejemplo, un nombre de columna cuando en realidad se usa 3.

Ejemplo:

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

La consulta solo devuelve 'col3' como una columna en el índice, pero el DDL muestra el conjunto completo de columnas utilizadas en el índice.

datico
fuente
0

Extienda a la buena respuesta de @ Cope360. Para obtener cierta tabla (en caso de que sea el mismo nombre de tabla pero diferente esquema), solo use el OID de la tabla.

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: Tengo el nombre de tabla 'tbassettype' en el esquema 'dbAsset' y 'dbLegal'. Para obtener solo la tabla en dbLegal, simplemente deje que a.attrelid = su OID.

Wutikrai
fuente
0

Una respuesta un poco 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;

Esto mostrará las columnas de índice en el orden correcto:

index_name      is_unique  column_name
pk_test         true       c
pk_test         true       a
pk_test         true       b
Nikita Ryanov
fuente
El uso de "left join pg_attribute" también mostrará índices en columnas calculadas, por supuesto con un nombre de columna NULL.
Paolo Bonzini el
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
fuente
0

La respuesta aceptada por @ cope360 es buena, pero quería algo un poco más como DBA_IND_COLUMNS, ALL_IND_COLUMNS de Oracle y USER_IND_COLUMNS (por ejemplo, informa el esquema de tabla / índice y la posición del índice en un índice de varias columnas), así que adapté el aceptado responde a esto:

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
;

Esto da una salida 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
fuente