Postgres和索引的外键和主键

Postgres会自动将索引放在外键和主键上吗? 我怎么知道 有没有一个将返回一个表中的所有索引的命令?

PostgreSQL自动在主键和唯一约束上创build索引,但不在外键关系的引用端。

当Pg创build一个隐式索引时,它会发出一个NOTICE -level消息,你可以在psql和/或系统日志中看到,所以你可以看到它发生的时间。 自动创build的索引也可以在\d输出中看到。

独特的索引文件说:

PostgreSQL自动为每个唯一的约束和主键约束创build一个索引来强制唯一性。 因此,没有必要为主键列创build索引。

和约束文件说:

由于从被引用的表中删除一行或引用列的UPDATE需要扫描与旧值匹配的行的引用表,因此索引引用列通常是一个好主意。 因为这并不总是需要的,并且有很多关于如何索引的选项,所以外键约束的声明不会自动在引用列上创build索引。

因此,如果你想要的话,你必须自己在外键上创build索引。

请注意,如果使用主键,如2 FK作为M到N表中的PK,则在PK上有一个索引,可能不需要创build任何额外的索引。

在引用端外键列上创build索引通常是一个好主意,但这不是必需的。 您添加的每个索引都会稍微减慢DML操作,因此您需要为每个INSERTUPDATEDELETE支付一定的性能成本。 如果指数很less使用,可能不值得拥有。

如果要从程序中列出模式中所有表的索引,则所有信息都将存储在目录中:

 select n.nspname as "Schema" ,t.relname as "Table" ,c.relname as "Index" 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 

如果您想深入研究(如列和sorting),您需要查看pg_catalog.pg_index。 使用psql -E [dbname]可以方便地找出如何查询目录。

是 – 对于主键,不 – 对于外键(更多在文档中 )。

 \d <table_name> 

在“psql”中显示了包含所有索引的表的描述。

此查询将列出外键 , 原始来源 缺less的索引

 -- check for FKs where there is no matching index -- on the referencing side -- or a bad index WITH fk_actions ( code, action ) AS ( VALUES ( 'a', 'error' ), ( 'r', 'restrict' ), ( 'c', 'cascade' ), ( 'n', 'set null' ), ( 'd', 'set default' ) ), fk_list AS ( SELECT pg_constraint.oid as fkoid, conrelid, confrelid as parentid, conname, relname, nspname, fk_actions_update.action as update_action, fk_actions_delete.action as delete_action, conkey as key_cols FROM pg_constraint JOIN pg_class ON conrelid = pg_class.oid JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid JOIN fk_actions AS fk_actions_update ON confupdtype = fk_actions_update.code JOIN fk_actions AS fk_actions_delete ON confdeltype = fk_actions_delete.code WHERE contype = 'f' ), fk_attributes AS ( SELECT fkoid, conrelid, attname, attnum FROM fk_list JOIN pg_attribute ON conrelid = attrelid AND attnum = ANY( key_cols ) ORDER BY fkoid, attnum ), fk_cols_list AS ( SELECT fkoid, array_agg(attname) as cols_list FROM fk_attributes GROUP BY fkoid ), index_list AS ( SELECT indexrelid as indexid, pg_class.relname as indexname, indrelid, indkey, indpred is not null as has_predicate, pg_get_indexdef(indexrelid) as indexdef FROM pg_index JOIN pg_class ON indexrelid = pg_class.oid WHERE indisvalid ), fk_index_match AS ( SELECT fk_list.*, indexid, indexname, indkey::int[] as indexatts, has_predicate, indexdef, array_length(key_cols, 1) as fk_colcount, array_length(indkey,1) as index_colcount, round(pg_relation_size(conrelid)/(1024^2)::numeric) as table_mb, cols_list FROM fk_list JOIN fk_cols_list USING (fkoid) LEFT OUTER JOIN index_list ON conrelid = indrelid AND (indkey::int2[])[0:(array_length(key_cols,1) -1)] @> key_cols ), fk_perfect_match AS ( SELECT fkoid FROM fk_index_match WHERE (index_colcount - 1) <= fk_colcount AND NOT has_predicate AND indexdef LIKE '%USING btree%' ), fk_index_check AS ( SELECT 'no index' as issue, *, 1 as issue_sort FROM fk_index_match WHERE indexid IS NULL UNION ALL SELECT 'questionable index' as issue, *, 2 FROM fk_index_match WHERE indexid IS NOT NULL AND fkoid NOT IN ( SELECT fkoid FROM fk_perfect_match) ), parent_table_stats AS ( SELECT fkoid, tabstats.relname as parent_name, (n_tup_ins + n_tup_upd + n_tup_del + n_tup_hot_upd) as parent_writes, round(pg_relation_size(parentid)/(1024^2)::numeric) as parent_mb FROM pg_stat_user_tables AS tabstats JOIN fk_list ON relid = parentid ), fk_table_stats AS ( SELECT fkoid, (n_tup_ins + n_tup_upd + n_tup_del + n_tup_hot_upd) as writes, seq_scan as table_scans FROM pg_stat_user_tables AS tabstats JOIN fk_list ON relid = conrelid ) SELECT nspname as schema_name, relname as table_name, conname as fk_name, issue, table_mb, writes, table_scans, parent_name, parent_mb, parent_writes, cols_list, indexdef FROM fk_index_check JOIN parent_table_stats USING (fkoid) JOIN fk_table_stats USING (fkoid) WHERE table_mb > 9 AND ( writes > 1000 OR parent_writes > 1000 OR parent_mb > 10 ) ORDER BY issue_sort, table_mb DESC, table_name, fk_name; 

对于PRIMARY KEY ,将使用以下消息创build索引:

 NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "index" for table "table" 

对于FOREIGN KEY ,如果引用表没有索引,则不会创build约束。

参考表上的索引不是必需的(虽然是期望的),因此不会被隐含地创build。

我喜欢这篇文章在EclipseLink 2.5的酷炫性能特性中的解释

索引外键

第一个function是自动索引外键。 大多数人不正确地认为数据库默认索引外键。 那么,他们不。 主键是自动索引的,但外键不是。 这意味着任何基于外键的查询都将进行全表扫描。 这是任何OneToManyManyToManyElementCollection关系,以及许多 OneToOne关系,以及涉及连接或对象比较的任何关系的大多数查询 。 这可能是一个主要的执行问题,你应该总是索引你的外键字段。