列出PostgreSQL中带索引的列

Luk*_*ncl 213 sql postgresql indexing

我想获得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      |         | 
+-------+------------+---------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
Run Code Online (Sandbox Code Playgroud)

PostgreSQL有这样的东西吗?

我已尝试\dpsql命令提示符下(带有-E显示SQL 的选项),但它没有显示我正在寻找的信息.

更新:感谢所有添加了答案的人.cope360给了我正是我想要的东西,但有几个人用非常有用的链接插话.有关将来的参考,请查看pg_index(通过Milen A. Radev)的文档和非常有用的文章从PostgreSQL中提取META信息(通过MichałNiklas).

cop*_*360 247

创建一些测试数据......

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));
Run Code Online (Sandbox Code Playgroud)

列出索引的索引和列:

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
Run Code Online (Sandbox Code Playgroud)

汇总列名:

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
Run Code Online (Sandbox Code Playgroud)

  • 对于任何试图在填充数据库中查找索引的人:此查询效果很好,但将`和t.relname更改为'test%'`行更改为您想要的表,或者完全删除该行以查找所有索引你的数据库. (22认同)
  • @Qwery,请参阅pg_class的文档`r =普通表,i =索引,S =序列,v =视图,c =复合类型,t = TOAST表`. (5认同)
  • 有没有办法也可以告诉密钥的唯一性? (2认同)
  • 要查看索引唯一性,还可以选择ix.indisunique (2认同)
  • @AndreKR,不,它没有列出正确的列顺序。为了获得正确的排序,我使用了“ORDER BY array_position(ix.indkey, a.attnum)” (2认同)

Mic*_*las 145

\d table_name显示此信息psql,但如果您想使用SQL从数据库获取此类信息,请查看从PostgreSQL提取META信息.

我在我的实用程序中使用这样的信息来报告来自db模式的一些信息,以比较测试和生产环境中的PostgreSQL数据库.


Val*_*tin 144

PostgreSQL(pg_indexes):

SELECT * FROM pg_indexes WHERE tablename = 'mytable';
Run Code Online (Sandbox Code Playgroud)

MySQL(SHOW INDEX):

SHOW INDEX FROM mytable;
Run Code Online (Sandbox Code Playgroud)

  • 这是最简单的答案,也是最有趣的回答问题"我的列是否被索引?" 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';`并验证结果集不为空. (3认同)
  • 尽管在检索有关索引的快速信息方面这是一个非常有用的答案,但它并没有回答原始问题,因为 `pg_indexes` 视图不提供列名。https://www.postgresql.org/docs/current/view-pg-indexes.html (3认同)

小智 74

做就是了: \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)
Run Code Online (Sandbox Code Playgroud)

它清楚地显示了给定索引的列在此表上.


seb*_*now 34

# \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)
Run Code Online (Sandbox Code Playgroud)

\di是该\d命令的"小兄弟" ,它将列出当前d atabase的所有关系.因此\di一定代表"告诉我这个d atabases 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-- 
Run Code Online (Sandbox Code Playgroud)

使用这两个命令,您可以在+其后添加一个以获取更多信息,例如索引所需的磁盘空间大小和描述(如果可用).

$ \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)
Run Code Online (Sandbox Code Playgroud)

在psql中,您可以轻松找到有关命令输入的帮助\?.

  • 但它不显示创建索引的列名.复合主键索引有许多列,无法看到. (2认同)

nao*_*oko 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;
Run Code Online (Sandbox Code Playgroud)


cop*_*360 11

一些样本数据......

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));
Run Code Online (Sandbox Code Playgroud)

使用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)
Run Code Online (Sandbox Code Playgroud)


Ary*_*yan 8

此命令也显示表变量,索引和约束的视图

=# \d table_name;
Run Code Online (Sandbox Code Playgroud)

例:

testannie=# \d dv.l_customer_account;
Run Code Online (Sandbox Code Playgroud)


Cor*_*rey 7

\d tablename 在版本8.3.8上显示我的列名称.

 "username_idx" UNIQUE, btree (username), tablespace "alldata1"
Run Code Online (Sandbox Code Playgroud)


小智 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)
Run Code Online (Sandbox Code Playgroud)

查询:

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;
Run Code Online (Sandbox Code Playgroud)


Mil*_*dev 5

原始信息位于pg_index中.


use*_*165 5

在使用索引时,索引中构建列的顺序与列本身一样重要。

以下查询以排序方式列出给定表的所有索引及其所有列。

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
Run Code Online (Sandbox Code Playgroud)

  • 为什么OP应该“尝试这个”?一个**好的答案**总是会解释所做的事情以及为什么这样做,不仅对于OP,而且对于未来可能会发现这个问题并阅读你的答案的SO访问者。 (2认同)

小智 5

@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
;
Run Code Online (Sandbox Code Playgroud)

这给出了如下输出:

 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)
Run Code Online (Sandbox Code Playgroud)