List columns with indexes in PostgreSQL

后端 未结 23 1926
我在风中等你
我在风中等你 2020-11-27 09:14

I would like to get the columns that an index is on in PostgreSQL.

In MySQL you can use SHOW INDEXES FOR table and look at the Column_name

相关标签:
23条回答
  • 2020-11-27 09:57

    Create some test data...

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

    List indexes and columns indexed:

    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
    

    Roll up the column names:

    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
    
    0 讨论(0)
  • 2020-11-27 09:57

    Just do: \d table_name

    But I'm not sure what do you mean that the information about columns is not there.

    For example:

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

    It clearly shows which columns given index is on this table.

    0 讨论(0)
  • 2020-11-27 09:58

    # \di

    The easies and shortest way is \di, which will list all the indexes in the current database.

    $ \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 is the "small brother" of the \d command which will list all relations of the current database. Thus \di certainly stand for "show me this databases indexes".

    Typing \diS will list all indexes used systemwide, which means you get all the pg_catalog indexes as well.

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

    With both these commands you can add a + after it to get even more information like the size the disk space the index needs and a description if available.

    $ \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 you can easily find help about commands typing \?.

    0 讨论(0)
  • 2020-11-27 09:58

    If you want to preserve column order in the index, here's a (very ugly) way to do that:

    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
    

    column order is stored in the pg_index.indkey column, so I ordered by the subscripts from that array.

    0 讨论(0)
  • 2020-11-27 09:58

    A little bit modified answer of @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;
    

    This will show the index columns in correct order:

    index_name      is_unique  column_name
    pk_test         true       c
    pk_test         true       a
    pk_test         true       b
    
    0 讨论(0)
提交回复
热议问题