Перерахуйте стовпці з індексами в 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 (через Michał Niklas ).


Просто для уточнення: Ви хочете, щоб ваша програма могла під час виконання з'ясувати, які стовпці індексуються, правда? На відміну від вас знає програмування.
Уейн Конрад

Так, правильно. В ідеалі я хочу, щоб оператор 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

24
Для тих, хто намагається знайти індекси в заселеній базі даних: цей запит працює чудово, але змініть and t.relname like 'test%'рядок у потрібну таблицю (и) або видаліть цей рядок повністю, щоб знайти всі індекси у вашому db.
Erik 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
Яна

177

PostgreSQL ( pg_indexes ):

SELECT * FROM pg_indexes WHERE tablename = 'mytable';

MySQL ( SHOW INDEX ):

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' ;і перевірити набір результатів не порожній.
нульова пропускна здатність

2
Хоча це дуже корисна відповідь щодо отримання швидкої інформації про індекси, вона не відповідає на початкове запитання, оскільки pg_indexesпредставлення не містить назв стовпців. postgresql.org/docs/current/view-pg-indexes.html
akagixxer

146

\d table_nameпоказує цю інформацію psql, але якщо ви хочете отримати таку інформацію з бази даних за допомогою SQL, перегляньте витяг інформації META з PostgreSQL .

Я використовую таку інформацію в своїй утиліті, щоб повідомити деяку інформацію зі схеми db для порівняння баз даних 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)

Це чітко показує, у яких стовпцях даний індекс знаходиться в цій таблиці.


Я сподівався на те, що дозволить мені зробити всі індекси на таблиці, але ти маєш рацію, \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команди, яка перелічить усі відносини поточної 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 ви можете легко знайти довідку щодо введення команд \?.


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)

Просто і ефективно!
Девід

Просто кльово. Мені пощастило, що я прокрутив цю відповідь.
greatvovan

8

Ці команди також показують перегляд змінних таблиць, індексів та обмежень

=# \d table_name;

Приклад:

testannie=# \d dv.l_customer_account;

7

\d tablename показує назви стовпців для мене у версії 8.3.8.

 "username_idx" UNIQUE, btree (username), tablespace "alldata1"

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)

ПИТАННЯ:

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;

приємний, проте назва "стовпця" для стовпця - це зарезервоване слово. IDEM для схеми, повинен використовувати
ім'я стовпця

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

2
Чому ОП повинна "спробувати це"? У хорошій відповіді завжди буде пояснення того, що було зроблено і чому це було зроблено не тільки для ОП, але і для майбутніх відвідувачів ТА, які можуть знайти це запитання та прочитати вашу відповідь.
Максиміліан Аст

iдля ordinality дуже слизьким. Це забезпечує колони в правильному порядку.
кброк

Це була єдина відповідь, яка працювала на мене. Порядок стовпців є критичним. (Якщо ви мені не вірите, шукайте всіх людей з прізвищем Франк у телефонній книзі.)
Юрай

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;

хороша примітка, але як отримати інформацію про те, що "нижня (
ім'я_ колонки

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

Не перераховано частини моїх індексів, які використовують функції (наприклад, "верхня (ім'я поля)").
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%'

`


Любіть це рішення. На жаль, це не вдається з індексами, де є пропозиції. (або інші круглі дужки)
кброк

Я змінив так, щоб не пропускати паролі на початку, і не захоплювати паронів посередині, а все після цього кидати. '^[^\)]*\(([^\)]*)\).*$'
кброк

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 показує повний набір стовпців, що використовуються в індексі.


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.


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 ім'ям стовпця.
Паоло

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 - це добре, але я хотів щось трохи більше, як DBA_IND_COLUMNS Oracle, ALL_IND_COLUMNS та USER_IND_COLUMNS Oracle (наприклад, повідомляє схему таблиці / індексу та положення індексу в багатоколінному індексі), тому я адаптував прийняте відповідь на це:

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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.