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. 主鍵和聚集索引
- 11. 索引變量和外鍵
- 12. 外鍵和索引問題
- 13. 對主鍵和外鍵以外的postgres列使用JSONB
- 14. SQL Server中的複合表,主鍵,外鍵和索引
- 15. 聚集索引的外鍵VS主鍵
- 16. ScalaQuery多主鍵和外鍵
- 17. 主鍵和外鍵2
- 18. SQL主鍵和外鍵
- 19. 主鍵和外鍵衝突
- 20. ORA-01735主鍵和外鍵
- 21. 外鍵和主鍵錯誤
- 22. Postgres索引最近的外鍵
- 23. 爲什麼postgres 9.3表會一直丟失主鍵和索引?
- 24. 索引外鍵
- 25. PLINQO主鍵和索引問題
- 26. 主鍵和索引 - 查詢性能
- 27. 爲性能選擇索引和主鍵
- 28. 關於SQL中的索引和主鍵?
- 29. Sybase唯一索引和主鍵
- 30. Postgres使用主鍵索引作爲覆蓋索引
我希望這個編輯是好的;我已經添加了相關文檔的鏈接,這個引用使得它完全明確地指出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