Listen Sie Spalten mit Indizes in PostgreSQL auf

233

Ich möchte die Spalten erhalten, in denen sich ein Index in PostgreSQL befindet.

In MySQL können Sie SHOW INDEXES FOR tabledie Column_nameSpalte verwenden und betrachten .

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

Gibt es so etwas für PostgreSQL?

Ich habe es \dan der psqlEingabeaufforderung versucht (mit der -EOption, SQL anzuzeigen), aber es werden nicht die Informationen angezeigt, nach denen ich suche.

Update: Vielen Dank an alle, die ihre Antworten hinzugefügt haben. Cope360 gab mir genau das, wonach ich suchte, aber mehrere Leute mischten sich mit sehr nützlichen Links ein. Weitere Informationen finden Sie in der Dokumentation zu pg_index (über Milen A. Radev ) und im sehr nützlichen Artikel Extrahieren von META-Informationen aus PostgreSQL (über Michał Niklas ).

Luke Francl
quelle
Nur zur Klarstellung: Sie möchten, dass Ihr Programm zur Laufzeit herausfinden kann, welche Spalten indiziert sind, oder? Im Gegensatz zu Ihnen das Programmierwissen.
Wayne Conrad
Ja richtig. Idealerweise möchte ich eine SQL-Anweisung, die NUR die Spalten auflistet, in denen sich der Index befindet. Aber ich weiß, PostgreSQL ist komplizierter als MySQL und der Index könnte sich auf eine Funktion usw.
beziehen

Antworten:

261

Erstellen Sie einige Testdaten ...

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

Indizes und indizierte Spalten auflisten:

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

Rollen Sie die Spaltennamen auf:

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
bewältigen360
quelle
24
Für alle, die versuchen, Indizes in einer aufgefüllten Datenbank zu finden: Diese Abfrage funktioniert hervorragend, aber ändern Sie die and t.relname like 'test%'Zeile in die gewünschte (n) Tabelle (n) oder löschen Sie diese Zeile vollständig, um alle Indizes in Ihrer Datenbank zu finden.
Erik J
1
Könnte jemand erklären, was relkind='r'bedeutet?
Qwerty
5
@Qwery, siehe Dokumentation zu pg_class r = ordinary table, i = index, S = sequence, v = view, c = composite type, t = TOAST table.
Cope360
1
Gibt es eine Möglichkeit, auch über die Eindeutigkeit des Schlüssels zu berichten?
Andrew
2
Um die Einzigartigkeit des Index zu sehen, wählen Sie auchix.indisunique
Jana
177

PostgreSQL ( pg_indexes ):

SELECT * FROM pg_indexes WHERE tablename = 'mytable';

MySQL ( SHOW INDEX ):

SHOW INDEX FROM mytable;
Valentin Podkamennyi
quelle
3
Dies ist die einfachste und interessanteste Antwort auf die Frage "Ist meine Spalte indiziert?" PostgreSQL: SELECT COUNT(indexname) AS indexcount FROM pg_indexes WHERE tablename='mytablename' AND indexdef LIKE '%mycolumnname%' ;und überprüfen indexcount>0. mySQL: SHOW INDEX FROM mytablename WHERE Column_name='mycolumnname' ;und überprüfen Sie, ob die Ergebnismenge nicht leer ist.
Nullbandbreite
2
Dies ist zwar eine sehr nützliche Antwort zum Abrufen schneller Informationen zu Indizes, beantwortet jedoch nicht die ursprüngliche Frage, da die pg_indexesAnsicht keine Spaltennamen enthält. postgresql.org/docs/current/view-pg-indexes.html
akagixxer
146

\d table_namezeigt diese Informationen aus an psql. Wenn Sie diese Informationen jedoch mithilfe von SQL aus der Datenbank abrufen möchten, lesen Sie Extrahieren von META-Informationen aus PostgreSQL .

Ich verwende solche Informationen in meinem Dienstprogramm, um einige Informationen aus dem Datenbankschema zu melden und PostgreSQL-Datenbanken in Test- und Produktionsumgebungen zu vergleichen.

Michał Niklas
quelle
Ihr Link zum Extrahieren von Metainformationen aus Postgres ist genau das, wonach ich gesucht habe! Mit den Tipps in diesem Thread und einigem Graben bin ich der Abfrage, die er in diesem Beitrag verwendet, ziemlich nahe gekommen, aber es ist schön, alles so angelegt zu haben.
Luke Francl
1
Ich verwende AWS RDS PostgreSQL 9.6.5 und \d tablezeige keine Indizes an, jedoch \dialle Indizes.
Hendy Irawan
@HendyIrawan kann es anscheinend durch andere Einstellungen beeinflusst werden. Wie ich mich frage, ob Sie den Modus "Nur Tupel" aktiviert hatten (umgeschaltet von \t). Wenn "nur Tupel" aktiviert ist, erhalte ich keine Indizes \d, wenn "nur Tupel" deaktiviert sind. Dies ist mit psql (PostgreSQL) 9.6.15.
JMM
77

Mach einfach: \d table_name

Aber ich bin mir nicht sicher, was Sie damit meinen, dass die Informationen über Spalten nicht vorhanden sind.

Beispielsweise:

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

Es wird deutlich, welche Spalten mit dem angegebenen Index in dieser Tabelle enthalten sind.

shilovk
quelle
Ich hatte auf etwas gehofft, mit dem ich alle Indizes für eine Tabelle erstellen kann, aber Sie haben Recht, \d index_namehaben die Informationen. So kann ich die Indizes einer Tabelle nachschlagen und dann die Details nachschlagen. Wenn ich die Spalten nicht zeige, meine ich, dass ich \d tablemir die durch den Namen generierte SQL angesehen habe und mir nicht klar ist, woher die Spaltenliste stammt. Ich denke, es wird aus der Indexdefinition heraus analysiert, was ich lieber nicht tun würde.
Luke Francl
Ich verwende AWS RDS PostgreSQL 9.6.5 und \d tablezeige keine Indizes an, jedoch \dialle Indizes.
Hendy Irawan
37

# \di

Der einfachste und kürzeste Weg ist \di, alle Indizes in der aktuellen Datenbank aufzulisten .

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

\diist der „kleine Bruder“ des \dBefehls , der alle Beziehungen der aktuellen Liste wird d ATENBANK. So \distehen sicherlich für „Zeigen Sie mir dieses d ATENBANKEN i ndexes“.

Typing \diSlistet alle Indizes system verwendet, das heißt , Sie alle die pg_catalog Indizes sowie bekommen.

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

Mit diesen beiden Befehlen können Sie ein Nachher hinzufügen +, um noch mehr Informationen wie die Größe des vom Index benötigten Speicherplatzes und eine Beschreibung, falls verfügbar, zu erhalten.

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

In psql finden Sie leicht Hilfe zur Eingabe von Befehlen \?.

sebisnow
quelle
2
Es werden jedoch nicht die Spaltennamen angezeigt, auf denen die Indizes erstellt werden. Der zusammengesetzte Primärschlüsselindex enthält viele Spalten, die nicht angezeigt werden.
Vignesh Raja
18

Kombiniert mit anderem Code und erstellt eine Ansicht:

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

Einige Beispieldaten ...

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

Verwendung pg_get_indexdefFunktion:

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)
bewältigen360
quelle
Einfach und effektiv!
David
Einfach super. Ich habe Glück, dass ich zu dieser Antwort gescrollt habe.
Greatvovan
8

Dieser Befehl zeigt auch die Ansicht von Tabellenvariablen, Indizes und Einschränkungen

=# \d table_name;

Beispiel:

testannie=# \d dv.l_customer_account;
arisch
quelle
7

\d tablename zeigt die Spaltennamen für mich in Version 8.3.8.

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

ERGEBNIS DER ABFRAGE:

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)

ABFRAGE:

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;
Trockenzeit
quelle
schön, aber der "Spalten" -Name für eine Spalte ist ein reserviertes Wort. IDEM für Schema, sollte Spaltenname
Parisni
5

Die Rohdaten befinden sich in pg_index .

Milen A. Radev
quelle
Interessant. Im Einzelnen indkey: "Dies ist ein Array von Indnatts-Werten, die angeben, welche Tabellenspalten dieser Index indiziert. Beispielsweise würde ein Wert von 1 3 bedeuten, dass die erste und die dritte Tabellenspalte den Indexschlüssel bilden. Eine Null in diesem Array gibt an, dass die Das entsprechende Indexattribut ist ein Ausdruck über den Tabellenspalten und keine einfache Spaltenreferenz. "
Luke Francl
2

Wenn Sie die Spaltenreihenfolge im Index beibehalten möchten, haben Sie folgende (sehr hässliche) Möglichkeit:

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

Die Spaltenreihenfolge wird in der Spalte pg_index.indkey gespeichert, daher habe ich nach den Indizes dieses Arrays sortiert.

David Willis
quelle
2

Beim Herumspielen mit Indizes ist die Reihenfolge, in der Spalten im Index erstellt werden, genauso wichtig wie die Spalten selbst.

In der folgenden Abfrage werden alle Indizes für eine bestimmte Tabelle und alle ihre Spalten sortiert aufgelistet.

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
quelle
2
Warum sollte das OP "dies versuchen"? Eine gute Antwort enthält immer eine Erklärung darüber, was getan wurde und warum dies so getan wurde, nicht nur für das OP, sondern auch für zukünftige Besucher von SO, die diese Frage möglicherweise finden und Ihre Antwort lesen.
Maximilian Ast
Das ifür die Ordinalität ist sehr glatt. Es stellt sicher, dass die Spalten in der richtigen Reihenfolge angegeben sind.
Kbrock
Dies war die einzige Antwort, die für mich funktioniert hat. Die Spaltenreihenfolge ist kritisch. (Wenn Sie mir nicht glauben, suchen Sie nach allen Personen mit einem Vornamen Frank in einem Telefonbuch.)
Juraj
1

Bitte versuchen Sie die folgende Abfrage, um einen Drilldown zu den erforderlichen Indizes durchzuführen

Abfrage wie unten - ich habe dies persönlich versucht und benutze es häufig.

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

Ähnlich wie bei der akzeptierten Antwort, aber wenn Sie den Join auf pg_attribute als normalen Join oder die Abfrage mit pg_attribute belassen haben, erhalten Sie keine Indizes wie:
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
quelle
gute Anmerkung, aber wie man Informationen über dieses "niedrigere (Spaltenname") "
erhält
1

Hier ist eine Funktion , die die Antwort von Bewältigung 360 umschließt:

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;

Verwendung:

select * from getIndices('<my_table>')
chribsen
quelle
Teile meiner Indizes, die Funktionen verwenden, wurden nicht aufgelistet (z. B. "Upper (Feldname)").
JohnMudd
0

Wie wäre es mit einer einfachen Lösung:

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
quelle
Ich liebe diese Lösung. Leider schlägt dies bei Indizes mit where-Klauseln fehl. (oder eine andere Klammer)
kbrock
Ich habe mich geändert, um am Anfang keine Parens zu überspringen und keine Parens in der Mitte zu erfassen und danach alles fallen zu lassen. '^[^\)]*\(([^\)]*)\).*$'
Kbrock
0

Die hervorragende Antwort von @cope360, konvertiert in die Join-Syntax.

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
quelle
0

Ich glaube, diese Version existiert noch nicht in diesem Thread: Sie enthält sowohl die Liste der Spaltennamen als auch die ddl für den Index.

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;

Ich habe festgestellt, dass Indizes, die Funktionen verwenden, nicht mit Spaltennamen verknüpft sind. Daher finden Sie gelegentlich eine Indexliste, z. B. einen Spaltennamen, wenn tatsächlich 3 verwendet wird.

Beispiel:

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

Die Abfrage gibt nur 'col3' als Spalte im Index zurück, aber die DDL zeigt den vollständigen Satz der im Index verwendeten Spalten an.

datico
quelle
0

Erweitern Sie auf gute Antwort von @ Cope360. Um für eine bestimmte Tabelle zu erhalten (falls sie denselben Tabellennamen, aber ein anderes Schema hat), verwenden Sie einfach die Tabellen-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;

Erklären Sie: Ich habe den Tabellennamen 'tbassettype' sowohl im Schema 'dbAsset' als auch in 'dbLegal'. Um nur eine Tabelle auf dbLegal zu erhalten, lassen Sie einfach a.attrelid = seine OID.

Wutikrai
quelle
0

Eine etwas modifizierte Antwort von @ 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;

Dadurch werden die Indexspalten in der richtigen Reihenfolge angezeigt:

index_name      is_unique  column_name
pk_test         true       c
pk_test         true       a
pk_test         true       b
Nikita Ryanov
quelle
Wenn Sie "left join pg_attribute" verwenden, werden auch Indizes für berechnete Spalten angezeigt, natürlich mit einem NULL-Spaltennamen.
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)
Guy Cohen
quelle
0

Die akzeptierte Antwort von @cope360 ist gut, aber ich wollte etwas mehr wie DBA_IND_COLUMNS, ALL_IND_COLUMNS und USER_IND_COLUMNS von Oracle (z. B. gibt das Tabellen- / Indexschema und die Position des Index in einem mehrspaltigen Index an), daher habe ich den akzeptierten angepasst antworte darauf:

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
;

Dies ergibt eine Ausgabe wie:

 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
quelle