在 Postgresql 中為主鍵和外鍵自動創建索引
對於 PostgreSQL 9.4 ( http://www.postgresql.org/docs/9.4/static/ddl-constraints.html ) 聲明
外鍵必須引用作為主鍵或形成唯一約束的列。這意味著被引用的列總是有一個索引(主鍵或唯一約束的基礎);因此檢查引用行是否匹配將是有效的。由於從引用表中刪除行或更新引用列將需要掃描引用表以查找與舊值匹配的行,因此索引引用列通常也是一個好主意。因為這並不總是需要,並且有很多關於如何索引的選擇,外鍵約束的聲明不會自動在引用列上創建索引。
我想知道這些行的作者是否忽略了一個要點:當我有一個父子關係(例如帶有購物車位置的購物車)時,孩子(購物車位置)標記了它與父母(購物車)的關係當我想獲取給定父級的所有子級時,使用父級(購物車)主鍵的外鍵我使用非索引外鍵列。
那麼,預設情況下不為外鍵列生成索引(與主鍵列相比)和讓使用者體驗次優性能的成本是否超過了維護索引的成本,在較小的表大小下,只做另一方面,查詢性能的微小改進?
也許有人對導致此決定的數據庫實現細節和推理有更多見解和/或可以指出為什麼外鍵列(在 Postgresql 中)的預設索引生成可能導致未被注意的嚴重問題的原因。
我不認為——外鍵列的預設索引生成——會導致嚴重的問題。
這只是 PostgreSQL 開發人員的一個決定,將這個選擇留給每個數據庫設計者/管理員。我們可以選擇在創建外鍵時添加或不添加索引。
如果他們做出相反的決定,那麼我們就會受到限制。每個外鍵約束都有一個索引。如果有人想讓一些外鍵列不被索引,他們會受到限製或強制。
現在只需要添加索引以匹配外鍵約束的額外負擔 - 對於那些想要的人來說。
就個人而言,我幾乎總是為外鍵約束添加相應的索引。但通常,索引與約束不完全匹配。例如,Fk 可能是
TABLE c (..., FOREIGN KEY (a_id) REFERENCES a (a_id) )
,索引可能是單一的(a_id)
或複合的(a_id, b_id)
,因為它也有助於其他查詢,而不僅僅是那些使用a_id
.或者我可能有(更罕見的情況)2個可以覆蓋但1個索引的外鍵約束 - 例如:
FK (a_id) REFERENCES a (a_id), ... FK (a_id, b_id) REFERENCES b (a_id, b_id)
.創建索引時,還有很多選項,比如索引的類型(
btree
、hash
、Gin、Gist 和其他奇異類型),因此我們可以自由選擇最適合我們情況的選項。另請注意,Oracle、SQL Server、DB2 和 Firebird 也不會自動為
FOREIGN KEY
列創建索引,因此 PostgreSQL 開發人員並不孤單。我敢肯定,關於這個問題有很多討論,他們考慮了這兩種選擇,我只是在猜測他們是為什麼做出這個決定的。查看舊的 Postgres 討論列表可能會更多地了解他們考慮的實際原因。