Список столбцов с индексами в PostgreSQL

233

Я хотел бы получить столбцы, по которым включен индекс в PostgreSQL.

В MySQL вы можете использовать SHOW INDEXES FOR tableи посмотреть на Column_nameстолбец.

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

Существует ли что-нибудь подобное для PostgreSQL?

Я попытался \dв psqlкомандной строке (с -Eвозможностью показать SQL), но он не показывает информацию, которую я ищу.

Обновление: спасибо всем, кто добавил свои ответы. cope360 дал мне именно то, что я искал, но несколько человек поделились очень полезными ссылками. Для дальнейшего ознакомления посмотрите документацию для pg_index (через Милена А. Радева ) и очень полезную статью Извлечение информации META из PostgreSQL (через Михала Никласа ).

Люк Франкл
источник
Просто чтобы уточнить: вы хотите, чтобы ваша программа могла во время выполнения выяснить, какие столбцы индексируются, верно? В отличие от вас знание программирования.
Уэйн Конрад
Да исправить. В идеале мне нужен оператор SQL, в котором перечислены ТОЛЬКО столбцы, к которым относится индекс. Но я знаю, что PostgreSQL сложнее, чем MySQL, и индекс может быть для функции и т. Д.
Люк Франк

Ответы:

261

Создать тестовые данные ...

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

Перечислите индексированные индексы и столбцы:

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

Сверните названия столбцов:

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
источник
24
Для любого, кто пытается найти индексы в заполненной базе данных: этот запрос отлично работает, но измените and t.relname like 'test%'строку на таблицы, которые вы хотите, или полностью удалите эту строку, чтобы найти все индексы в вашей базе данных.
Эрик J
1
Может кто-нибудь объяснить, что relkind='r'значит?
Qwerty
5
@Qwery, смотрите документацию по pg_class r = ordinary table, i = index, S = sequence, v = view, c = composite type, t = TOAST table.
cope360
1
Есть ли способ также рассказать об уникальности ключа?
Андрей
2
чтобы увидеть уникальность индекса также выберитеix.indisunique
Jana
177

PostgreSQL ( pg_indexes ):

SELECT * FROM pg_indexes WHERE tablename = 'mytable';

MySQL ( ПОКАЗАТЬ ИНДЕКС ):

SHOW INDEX FROM mytable;
Валентин Подкаменный
источник
3
Это самый простой ответ, и самый интересный с точки зрения ответа на вопрос «Индексируется ли моя колонка?» PostgreSQL: SELECT COUNT(indexname) AS indexcount FROM pg_indexes WHERE tablename='mytablename' AND indexdef LIKE '%mycolumnname%' ;и проверьте indexcount>0. MySQL: SHOW INDEX FROM mytablename WHERE Column_name='mycolumnname' ;и проверить набор результатов не пустой.
zerobandwidth
2
Хотя это очень полезный ответ с точки зрения получения быстрой информации об индексах, он не отвечает на исходный вопрос, поскольку pg_indexesпредставление не содержит имен столбцов. postgresql.org/docs/current/view-pg-indexes.html
akagixxer
146

\d table_nameпоказывает эту информацию из psql, но если вы хотите получить такую ​​информацию из базы данных, используя SQL, посмотрите на Извлечение информации META из PostgreSQL .

Я использую такую ​​информацию в своей утилите, чтобы сообщить некоторую информацию из схемы БД для сравнения баз данных PostgreSQL в тестовой и производственной средах.

Михал Никлас
источник
Ваша ссылка на извлечение метаинформации из Postgres - это именно то, что я искал! Используя подсказки в этой теме и некоторые раскопки, я довольно близко подошел к запросу, который он использует в этом посте, но приятно, что все это изложено так.
Люк Франк
1
Я использую AWS RDS PostgreSQL 9.6.5 и \d tableне показывает никаких индексов, однако \diпоказывает все индексы.
Хенди Ираван
@HendyIrawan на это могут повлиять другие настройки. Как будто мне интересно, был ли у вас режим "только для кортежей" (переключается \t). При включенном «только кортежи» я не получаю индексы \d, при отключенном «только кортежи» я получаю. Это с psql (PostgreSQL) 9.6.15.
JMM
77

Просто сделать: \d table_name

Но я не уверен, что вы имеете в виду, что информации о столбцах нет.

Например:

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

Это ясно показывает, какие столбцы данного индекса находятся в этой таблице.

shilovk
источник
Я надеялся на что-то, что позволит мне сделать все индексы в таблице, но вы правы, у \d index_nameвас есть информация. Так что я могу посмотреть на индексы в таблице, а затем посмотреть детали. Не показывая столбцы, я имею в виду, что я посмотрел на SQL, сгенерированный по \d tableимени, и для меня не очевидно, откуда берется список столбцов. Я думаю, что это анализируется из определения индекса, что я предпочел бы не делать.
Люк Франк
Я использую AWS RDS PostgreSQL 9.6.5 и \d tableне показывает никаких индексов, однако \diпоказывает все индексы.
Хенди Ираван
37

# \di

Самый простой и краткий способ - \diперечислить все индексы в текущей базе данных.

$ \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это «младший брат» из \dкоманды , которая перечислит все отношения текущего г atabase. Таким образом , \diконечно , стоять на «показать мне это d atabases I ndexes».

При наборе \diSбудут перечислены все индексы, используемые в системе, что означает, что вы также получите все индексы 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-- 

Обе эти команды вы можете добавить +после, чтобы получить еще больше информации, такой как размер дискового пространства, необходимого для индекса, и описание, если оно доступно.

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

В psql вы можете легко найти справку о наборе команд \?.

sebisnow
источник
2
Но он не показывает имена столбцов, по которым создаются индексы. Сводный индекс первичных ключей имеет много столбцов, и их нельзя увидеть.
Виньеш Раджа
18

В сочетании с другим кодом и создал вид:

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;
Наоко
источник
12

Некоторые примеры данных ...

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

Используйте pg_get_indexdefфункцию:

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
источник
Просто и эффективно!
Дэвид
Просто восхитительно. Мне повезло, что я прокрутил этот ответ.
Greatvovan
8

Эта команда также показывает представление переменных, индексов и ограничений таблиц

=# \d table_name;

Пример:

testannie=# \d dv.l_customer_account;
арийский
источник
7

\d tablename показывает имена столбцов для меня в версии 8.3.8.

 "username_idx" UNIQUE, btree (username), tablespace "alldata1"
Corey
источник
7

РЕЗУЛЬТАТ ЗАПРОСА:

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;
Dryymoon
источник
хороший, однако имя столбца для столбца является зарезервированным словом. IDEM для схемы, следует использовать column_name
parisni
5

Необработанная информация находится в pg_index .

Милен А. Радев
источник
Интересный. В частности indkey: «Это массив значений indnatts, которые указывают, какие столбцы таблицы этот индекс индексирует. Например, значение 1 3 будет означать, что первый и третий столбцы таблицы составляют ключ индекса. Ноль в этом массиве указывает, что соответствующий атрибут индекса является выражением над столбцами таблицы, а не простой ссылкой на столбец "
Люк Франк
2

Если вы хотите сохранить порядок столбцов в индексе, вот (очень уродливый) способ сделать это:

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

порядок столбцов хранится в столбце pg_index.indkey, поэтому я упорядочил подписчики из этого массива.

Дэвид Уиллис
источник
2

При игре с индексами порядок составления столбцов в индексе так же важен, как и сами столбцы.

Следующий запрос перечисляет все индексы для данной таблицы и все их столбцы в отсортированном виде.

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
источник
2
Почему ОП "попробовать это"? Хороший ответ всегда будет объяснение того , что было сделано и почему это было сделано именно так, а не только для OP , но для посетителей в будущем так , что может найти этот вопрос и будет читать ваш ответ.
Максимилиан Аст
iдля ordinality очень скользким. Это гарантирует, что столбцы указаны в правильном порядке.
kbrock
Это был единственный ответ, который работал для меня. Порядок столбцов является критическим. (Если вы мне не верите, поищите всех людей с именем Фрэнк в телефонной
Juraj
1

Пожалуйста, попробуйте запрос ниже, чтобы перейти к нужным индексам

Запрос, как показано ниже - я пробовал это лично и часто его использую.

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;
Барат Равичандер
источник
1

Подобно принятому ответу, но оставив соединение на pg_attribute как обычное соединение или запрос с pg_attribute, не дает индексы, которые выглядят как:
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;
Нихилу
источник
Хорошая заметка, но как получить информацию об этом "нижнем (column_name") "
pleerock
1

Вот функция, которая оборачивает ответ 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;

Использование:

select * from getIndices('<my_table>')
chribsen
источник
Не перечислил части моих индексов, которые используют функции (например, "upper (field_name)").
JohnMudd
0

Как насчет простого решения:

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
источник
Люблю это решение. К сожалению, это не с индексами, которые имеют предложения where. (или другие круглые скобки)
Кброк
Я изменил, чтобы не пропускать парены в начале, и не захватывать парни в середине, и бросать все после этого. '^[^\)]*\(([^\)]*)\).*$'
Кброк
0

Отличный ответ @ cope360, преобразованный для использования синтаксиса соединения.

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
;
Кристиан Лонг
источник
0

Я не думаю, что эта версия еще существует в этом потоке: она предоставляет как список имен столбцов, так и ddl для индекса.

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;

Я обнаружил, что индексы, использующие функции, не связываются с именами столбцов, поэтому иногда вы видите список индексов, например, одно имя столбца, когда на самом деле используется 3.

Пример:

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

Запрос возвращает только «col3» в качестве столбца в индексе, но DDL показывает полный набор столбцов, используемых в индексе.

datico
источник
0

Продлите до хорошего ответа @ Cope360. Чтобы получить для определенной таблицы (в том случае, если это то же имя таблицы, но разные схемы), просто используя таблицу 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;

Объясните: у меня есть имя таблицы 'tbassettype' в обеих схемах 'dbAsset' и 'dbLegal'. Чтобы получить только таблицу на dbLegal, просто позвольте a.attrelid = его OID.

Wutikrai
источник
0

Немного модифицированный ответ @ 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;

Это покажет столбцы индекса в правильном порядке:

index_name      is_unique  column_name
pk_test         true       c
pk_test         true       a
pk_test         true       b
Никита Рьянов
источник
Использование «left join pg_attribute» также покажет индексы для вычисляемых столбцов, конечно, с NULL column_name.
Паоло Бонзини
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)
Гай Коэн
источник
0

Принятый ответ @ cope360 хорош, но я хотел что-то более похожее на Oracle DBA_IND_COLUMNS, ALL_IND_COLUMNS и USER_IND_COLUMNS (например, сообщает схему таблицы / индекса и положение индекса в многоколоночном индексе), поэтому я адаптировал принятый ответь на это:

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
;

Это дает вывод как:

 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)
Стивен
источник