Liệt kê các cột có chỉ mục trong PostgreSQL


233

Tôi muốn lấy các cột có chỉ mục trong PostgreSQL.

Trong MySQL bạn có thể sử dụng SHOW INDEXES FOR tablevà nhìn vào Column_namecột.

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

Có bất cứ điều gì như thế này tồn tại cho PostgreSQL?

Tôi đã thử \dtại psqldấu nhắc lệnh (với -Etùy chọn hiển thị SQL) nhưng nó không hiển thị thông tin tôi đang tìm kiếm.

Cập nhật: Cảm ơn tất cả những người đã thêm câu trả lời của họ. cope360 đã cho tôi chính xác những gì tôi đang tìm kiếm, nhưng một số người đã theo đuổi với các liên kết rất hữu ích. Để tham khảo trong tương lai, hãy xem tài liệu về pg_index (thông qua Milen A. Radev ) và bài viết rất hữu ích Trích xuất thông tin META từ PostgreQuery (thông qua Michał Niklas ).


Chỉ cần làm rõ: Bạn muốn chương trình của bạn có thể tìm ra, trong thời gian chạy, cột nào được lập chỉ mục, phải không? Trái ngược với bạn là lập trình biết.
Wayne Conrad

Vâng chính xác. Lý tưởng nhất là tôi muốn một câu lệnh SQL liệt kê CHỈ các cột mà chỉ mục được bật. Nhưng tôi biết PostgreSQL phức tạp hơn MySQL và chỉ mục có thể nằm trên một chức năng, v.v.
Luke Francl

Câu trả lời:


261

Tạo một số dữ liệu thử nghiệm ...

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

Liệt kê các chỉ mục và các cột được lập chỉ mục:

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

Cuộn tên cột:

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
Đối với bất kỳ ai đang cố gắng tìm các chỉ mục trong cơ sở dữ liệu đông dân cư: truy vấn này hoạt động rất tốt, nhưng thay đổi and t.relname like 'test%'dòng thành (các) bảng bạn muốn hoặc xóa hoàn toàn dòng đó để tìm tất cả các chỉ mục trong db của bạn.
Erik J

1
Ai đó có thể giải thích những gì relkind='r'có nghĩa là?
Qwerty

5
@Qwery, xem tài liệu cho pg_group r = ordinary table, i = index, S = sequence, v = view, c = composite type, t = TOAST table.
cope360

1
Có cách nào để nói về tính độc đáo của chìa khóa không?
Andrew

2
để xem tính duy nhất của chỉ mục cũng chọnix.indisunique
Jana

177

PostgreSQL ( pg_indexes ):

SELECT * FROM pg_indexes WHERE tablename = 'mytable';

MySQL ( SHOW INDEX ):

SHOW INDEX FROM mytable;

3
Đây là câu trả lời đơn giản nhất và thú vị nhất khi trả lời câu hỏi "Cột của tôi có được lập chỉ mục không?" PostgreSQL: SELECT COUNT(indexname) AS indexcount FROM pg_indexes WHERE tablename='mytablename' AND indexdef LIKE '%mycolumnname%' ;và xác minh indexcount>0. myQuery: SHOW INDEX FROM mytablename WHERE Column_name='mycolumnname' ;và xác minh tập kết quả không trống.
zerobandference

2
Mặc dù đây là một câu trả lời rất hữu ích trong việc truy xuất thông tin nhanh về các chỉ mục nhưng nó không trả lời câu hỏi ban đầu vì pg_indexeschế độ xem không cung cấp tên cột. postgresql.org/docs/civerse/view-pg-indexes.html
akagixxer

146

\d table_namehiển thị thông tin này từ psql, nhưng nếu bạn muốn lấy thông tin đó từ cơ sở dữ liệu bằng SQL thì hãy xem Trích xuất thông tin META từ PostgreQuery .

Tôi sử dụng thông tin như vậy trong tiện ích của mình để báo cáo một số thông tin từ lược đồ db để so sánh cơ sở dữ liệu PostgreQuery trong môi trường thử nghiệm và sản xuất.


Liên kết của bạn về trích xuất thông tin meta từ Postgres chính xác là những gì tôi đang tìm kiếm! Sử dụng các mẹo trong chủ đề này và một số hoạt động đào tôi đã khá gần với truy vấn anh ta sử dụng trong bài đăng đó, nhưng thật tuyệt khi tất cả đều được trình bày như thế.
Luke Francl

1
Tôi đang sử dụng AWS RDS PostgreSQL 9.6.5 và \d tablekhông hiển thị bất kỳ chỉ mục nào, tuy nhiên \dikhông hiển thị tất cả các chỉ mục.
Hendy I Girls

@HendyIINA nó rõ ràng có thể bị ảnh hưởng bởi các cài đặt khác. Giống như tôi tự hỏi nếu bạn có chế độ "tuples only" (bật tắt \t). Với "tuples only" trên, tôi không nhận được chỉ mục từ \d, với "tuples only" tắt, tôi làm. Đây là với psql (PostgreSQL) 9.6.15.
JMM

77

Cứ làm đi: \d table_name

Nhưng tôi không chắc ý bạn là gì mà thông tin về các cột không có ở đó.

Ví dụ:

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

Nó cho thấy rõ các cột đã cho chỉ mục nằm trên bảng này.


Tôi đã hy vọng điều gì đó sẽ cho phép tôi thực hiện tất cả các chỉ mục trên một bảng nhưng bạn nói đúng, \d index_namecó thông tin. Vì vậy, tôi có thể tra cứu các chỉ mục trên một bảng, sau đó tìm kiếm các chi tiết. Bằng cách không hiển thị các cột, ý tôi là tôi đã xem SQL được tạo theo \d tabletên và tôi không rõ danh sách cột đến từ đâu. Tôi nghĩ rằng nó đã được phân tích ra khỏi định nghĩa chỉ mục, điều mà tôi không muốn làm.
Luke Francl

Tôi đang sử dụng AWS RDS PostgreSQL 9.6.5 và \d tablekhông hiển thị bất kỳ chỉ mục nào, tuy nhiên \dikhông hiển thị tất cả các chỉ mục.
Hendy I Girls

37

# \di

Các tiện ích và cách ngắn nhất là \di, sẽ liệt kê tất cả các chỉ mục trong cơ sở dữ liệu hiện tại.

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

\dilà "anh trai nhỏ" của \dlệnh này sẽ liệt kê tất cả các mối quan hệ của dòng điện d atabase. Như vậy \dichắc chắn đại diện cho "chỉ cho tôi này d atabases i ndexes".

Nhập \diSsẽ liệt kê tất cả các chỉ mục được sử dụng trên toàn hệ thống, có nghĩa là bạn cũng nhận được tất cả các chỉ mục 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-- 

Với cả hai lệnh này, bạn có thể thêm một lệnh +sau để có thêm thông tin như kích thước không gian đĩa mà chỉ mục cần và mô tả nếu có.

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

Trong psql bạn có thể dễ dàng tìm thấy sự trợ giúp về các lệnh gõ \?.


2
Nhưng nó không hiển thị tên cột mà các chỉ mục được tạo. Chỉ số khóa chính tổng hợp có nhiều cột và không thể nhìn thấy các cột.
Vignesh Raja

18

Kết hợp với mã khác và tạo ra một khung nhìn:

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

Một số dữ liệu mẫu ...

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

Sử dụng pg_get_indexdefchức năng:

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)

Đơn giản và hiệu quả!
David

Tuyệt vời. Tôi may mắn tôi đã cuộn đến câu trả lời này.
greatvovan

8

Lệnh này cũng hiển thị khung nhìn của các biến bảng, chỉ mục và các ràng buộc

=# \d table_name;

Thí dụ:

testannie=# \d dv.l_customer_account;

7

\d tablename hiển thị tên cột cho tôi trên phiên bản 8.3.8.

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

7

KẾT QUẢ SỐ LƯỢNG:

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)

TRUY VẤN:

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;

một cái hay, tuy nhiên tên "cột" cho một cột là một từ dành riêng. IDEM cho lược đồ, nên sử dụng
cột_name

5

Thông tin thô có trong pg_index .


Hấp dẫn. Cụ thể indkey: "Đây là một mảng các giá trị indnatts cho biết cột nào chỉ mục này chỉ mục này. Ví dụ: giá trị 1 3 có nghĩa là cột cột thứ nhất và thứ ba tạo nên khóa chỉ mục. Một số 0 trong mảng này chỉ ra rằng thuộc tính chỉ mục tương ứng là một biểu thức trên các cột của bảng, chứ không phải là một tham chiếu cột đơn giản "
Luke Francl

2

Nếu bạn muốn duy trì thứ tự cột trong chỉ mục, đây là một cách (rất xấu) để làm điều đó:

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

thứ tự cột được lưu trữ trong cột pg_index.indkey, vì vậy tôi đã sắp xếp theo các mục con từ mảng đó.


2

Khi chơi xung quanh với các chỉ mục, thứ tự các cột được xây dựng trong chỉ mục cũng quan trọng như chính các cột.

Truy vấn sau đây liệt kê tất cả các chỉ mục cho một bảng nhất định và tất cả các cột của chúng theo cách được sắp xếp.

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
Tại sao OP nên "thử cái này"? Một câu trả lời hay sẽ luôn có lời giải thích về những gì đã được thực hiện và tại sao nó được thực hiện theo cách đó, không chỉ cho OP mà cả những khách truy cập tương lai của SO có thể tìm thấy câu hỏi này và đang đọc câu trả lời của bạn.
Maximilian Ast

các ipháp lệnh là rất trơn tru. Nó đảm bảo các cột được nêu theo đúng thứ tự.
kbrock

Đây là câu trả lời duy nhất làm việc cho tôi. Thứ tự cột là rất quan trọng. (Nếu bạn không tin tôi, hãy tìm tất cả những người có tên Frank trong danh bạ.)
Juraj

1

Vui lòng thử truy vấn bên dưới để xem chi tiết yêu cầu

Truy vấn như dưới đây - tôi đã thử cá nhân này và sử dụng nó thường xuyên.

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

Tương tự như câu trả lời được chấp nhận nhưng việc rời khỏi tham gia trên pg_attribution như tham gia bình thường hoặc truy vấn với pg_attribution không đưa ra các chỉ số giống như:
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;

lưu ý tốt, nhưng làm thế nào để có được thông tin về "thấp hơn (cột_name") "
pleerock

1

Đây là một chức năng kết thúc câu trả lời của 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;

Sử dụng:

select * from getIndices('<my_table>')

Không liệt kê các phần trong chỉ mục của tôi sử dụng các hàm (ví dụ: "phía trên (tên trường)").
JohnMudd

0

Làm thế nào về một giải pháp đơn giản:

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

`


Yêu giải pháp này. Thật không may, nó thất bại với các chỉ mục có mệnh đề. (hoặc dấu ngoặc đơn khác)
kbrock

Tôi đã thay đổi để không bỏ qua parens lúc đầu, và không bắt được parens ở giữa, và bỏ mọi thứ sau đó. '^[^\)]*\(([^\)]*)\).*$'
kbrock

0

Câu trả lời tuyệt vời của @ cope360, được chuyển đổi sang sử dụng cú pháp nối.

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

Tôi không nghĩ phiên bản này tồn tại trên luồng này: nó cung cấp cả danh sách các tên cột cùng với ddl cho chỉ mục.

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;

Tôi thấy rằng các chỉ mục sử dụng các hàm không liên kết đến các tên cột, vì vậy đôi khi bạn tìm thấy một danh sách chỉ mục, ví dụ như một tên cột khi thực tế sử dụng 3.

Thí dụ:

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

Truy vấn chỉ trả về 'col3' dưới dạng một cột trên chỉ mục, nhưng DDL hiển thị toàn bộ các cột được sử dụng trong chỉ mục.


0

Mở rộng để trả lời tốt của @ Giao360. Để có được một bảng nhất định (bao gồm tên bảng giống nhau nhưng lược đồ khác nhau), chỉ cần sử dụng bảng 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;

Giải thích: Tôi có tên bảng 'tbassettype' trong cả hai lược đồ 'dbAsset' và 'dbLegal'. Để chỉ nhận bảng trên dbLegal, chỉ cần cho a.attrelid = OID của nó.


0

Một câu trả lời sửa đổi một chút của @ 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;

Điều này sẽ hiển thị các cột chỉ mục theo đúng thứ tự:

index_name      is_unique  column_name
pk_test         true       c
pk_test         true       a
pk_test         true       b

Sử dụng "pg_attribution bên trái" cũng sẽ hiển thị các chỉ mục trên các cột được tính toán, tất nhiên với một cột tên NULL.
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)

0

Câu trả lời được chấp nhận bởi @ cope360 là tốt, nhưng tôi muốn một cái gì đó giống như DBA_IND_COLUMNS, ALL_IND_COLUMNS và USER_IND_COLUMNS của Oracle (ví dụ: báo cáo lược đồ bảng / chỉ mục và vị trí của chỉ mục trong chỉ mục nhiều màu) trả lời vào đây

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
;

Điều này mang lại một đầu ra như:

 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)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.