Postgres是否自动将索引放在外键和主键上?我怎么知道?有没有能够返回表中所有索引的命令?外键和主键Postgres和索引
回答
PostgreSQL自动在主键和唯一约束上创建索引,但不在外键关系的引用端创建索引。
当Pg创建隐式索引时,它将发出一个NOTICE
级别的消息,您可以在psql
和/或系统日志中看到,以便您可以看到它何时发生。自动创建的索引在\d
输出中也可见。
documentation on unique indexes的说:
PostgreSQL自动为每个唯一约束和主键约束强制唯一性的指标。因此,没有必要为主键列显式创建索引。
和constraints的文件说:
由于删除引用表或 引用的列的更新行的,需要引用表的 行匹配的扫描旧值的情况下,索引 引用列通常是个好主意。因为这并不总是需要的,并且 有许多关于如何索引的选项,所以外键约束的声明 约束不会自动在引用 列中创建索引。
因此,如果您需要,您必须自己在外键上创建索引。
请注意,如果您使用主键 - 外键,如2 FK作为M到N表中的PK,则您将拥有PK索引,并且可能不需要创建任何额外索引。
虽然在引用端外键列上创建索引通常是一个好主意,但并不是必需的。您添加的每个索引都会使DML操作略微减慢,因此您需要为每个INSERT
,UPDATE
或DELETE
支付一次性能成本。如果该指数很少使用,它可能不值得拥有。
对于PRIMARY KEY
,索引将使用以下信息来创建:
NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index "index" for table "table"
对于FOREIGN KEY
,约束不会如果有上中借鉴编表中没有索引创建。
有关引用的索引ing表不是必需的(尽管需要),因此不会被隐式创建。
如果要列出所有表的索引,从你的程序的模式(S),所有的信息是手头上的目录:
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
如果你想进一步深入研究(例如作为列和排序),您需要查看pg_catalog.pg_index。使用psql -E [dbname]
可以方便地找出如何查询目录。
此查询将列出外键丢失索引,original source。
-- 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;
我爱怎么这是文章Cool performance features of EclipseLink 2.5
索引外键
中介绍的第一个特点是外键的自动索引。大多数人错误地认为数据库默认索引 外键。那么,他们没有。主键为自动编号 ,但外键不是。这意味着任何基于 外键的查询都将进行全表扫描。这是任何一对多, 多对多或ElementCollection关系,以及许多OneToOne 关系,大多数查询都是对涉及任何关系连接或 的对象比较。这可能是一个主要的执行问题,您应该始终索引您的外键字段。
- 1. 外键和索引
- 2. 外键和索引
- 3. 主键和外键
- 4. 主键和外键
- 5. 主键和外键?
- 6. 境界索引和主键
- 7. 主键和索引概念
- 8. 外键和索引问题
- 9. 索引变量和外键
- 10. 对主键和外键以外的postgres列使用JSONB
- 11. SQL Server中的复合表,主键,外键和索引
- 12. 聚集索引的外键VS主键
- 13. ORA-01735主键和外键
- 14. 外键和主键错误
- 15. ScalaQuery多主键和外键
- 16. 主键和外键2
- 17. Postgres索引最近的外键
- 18. 索引外键
- 19. 关于SQL中的索引和主键?
- 20. PLINQO主键和索引问题
- 21. 为性能选择索引和主键
- 22. Postgres使用主键索引作为覆盖索引
- 23. SQL Server 2005外键和索引
- 24. MySQL的外键和索引优化
- 25. Postgres主键Synchornized
- 26. 同一表中的主键和外键
- 27. 主键和外键同时出现
- 28. 需要主键和外键的帮助
- 29. SQL更改语句和外键/主键
- 30. Ruby on Rails - 主键和外键
我希望这个编辑是好的;我已经添加了相关文档的链接,这个引用使得它完全明确地指出FK关系的引用方不会产生隐式索引,显示了如何在psql中查看索引,为了清晰起见而修改了第一个参数,并添加了一个请注意,索引不是免费的,所以添加它们并不总是正确的。 – 2012-08-23 05:16:32
@CraigRinger,你如何确定指数的收益是否超过其成本?我是否在添加索引之前/之后对单元测试进行剖析并检查总体性能增益?或者,还有更好的方法? – Gili 2014-11-25 05:00:32
@Gili这是一个单独的dba.stackexchange.com问题的主题。 – 2014-11-25 05:04:09