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:53

    When playing around with indexes the order of which columns are constructed in the index is as important as the columns themselves.

    The following query lists all indexes for a given table and all their columns in a sorted fashion.

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

    Similar to the accepted answer but having left join on pg_attribute as normal join or query with pg_attribute doesnt give indices which are like :
    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;
    
    0 讨论(0)
  • 2020-11-27 09:55

    The raw info is in pg_index.

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

    Here's a function that wraps cope360's answer:

    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;
    

    Usage:

    select * from getIndices('<my_table>')
    
    0 讨论(0)
  • 2020-11-27 09:56

    RESULT OF QUERY:

    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)
    

    QUERY:

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

    \d tablename shows the column names for me on version 8.3.8.

     "username_idx" UNIQUE, btree (username), tablespace "alldata1"
    
    0 讨论(0)
提交回复
热议问题