Index

Oracle 中的一個索引支持 2 個約束是否有任何潛在問題?

  • November 11, 2012

我有下表:

CREATE TABLE action (action_id INT NOT NULL,
action_type_id INT NOT NULL,
action_date DATE NOT NULL);
CREATE INDEX IDX_ACTION_ACT_TYPE_ACT ON action(action_id, action_type_id);
ALTER TABLE action ADD CONSTRAINT PK_ACTION PRIMARY KEY (action_id) 
 USING INDEX IDX_ACTION_ACT_TYPE_ACT;
ALTER TABLE action ADD CONSTRAINT UQ_ACTION UNIQUE (action_id,action_type_id) 
 USING INDEX IDX_ACTION_ACT_TYPE_ACT;
-- I think the line below is irrelevant in the context of my question, but 
-- in case I'm wrong... 
ALTER TABLE action ADD CONSTRAINT FK_action_type_id FOREIGN KEY(action_type_id) 
REFERENCES action_type(action_type_id);
-- Since action_type is a lookup added for normalization sake with no updates/deletes,
-- I don't see any value in having an index on FK column. 

對於儲存特定操作的額外資訊的許多詳細資訊表來說,它是一個通用父表。action_type_id是唯一約束的一部分,它讓詳細表具有對 (action_id,action_type_id) 的 FK,並強制每個詳細表只儲存它應該儲存的資訊。

我想知道與創建 2 個索引相比,在 2 個約束中使用相同的索引是否有任何性能損失……在我看來,它應該比 2 個索引表現得更好,但也許我遺漏了一些東西。如果這很重要,我正在使用 Oracle 10g。

謝謝您的回答。

正如 Nat 所指出的,您的 UQ_ACTION 約束複製了主鍵約束。根據您在此表中的 FK 使用情況,您的主鍵是 (action_id, action_type_id)。因此它是多餘的,應該被刪除。如果您希望您的主鍵單獨為 action_id,那麼您的外鍵必須僅引用 action_id。

我相信您將 action_id 建模為主鍵是正確的。在這種情況下,更改您的子引用。(在外鍵中包含操作類型 id 違反了正常形式,並強制將冗餘資訊放入引用表中。)。如果您的操作表的子表適用於多種類型,則它們的鍵中將包含操作類型 ID。

您可能希望在 action_id 上使用 UK,但這不是必需的。如果您有這樣一個帶有相應索引的英國,那麼我會顛倒包含(action_type_id,action_id)的索引的順序。這將允許單獨通過 action_id 和通過 action_type_id 進行快速檢索,其中統計數據表明索引是有用的。

但是,在索引可用於多個約束的情況下回答您的問題,沒有任何懲罰。事實上,情況恰恰相反。

維護索引可能是一項相對昂貴的操作。添加冗餘索引確實有懲罰。更改冗餘索引中的列的每次插入、更新或刪除都需要額外的工作來更新索引。

看來您已經認識到不創建未使用索引的價值。雖然很常見,但在許多情況下,外鍵索引並不是必需的。如果您確實從引用的表中刪除,最好有一個索引。以外鍵開頭的代理索引可能會導致更有效的查詢。如果您通過 action_type_id 進行頻繁查找,則該索引將很有用。具有用於過濾結果集的其他值的多列索引可能更有用。

引用自:https://dba.stackexchange.com/questions/28518