我只是將一些外鍵添加到我的數據庫中,並且通常我的所有外鍵都不識別,因爲我從來沒有打擾過讓他們識別,因爲我從來不知道它們的差別和我的數據庫總是對我來說似乎工作得很好。外鍵識別與非識別關係之間的性能差異
現在我已經決定我要正確創建這個數據庫並且正在使外鍵識別和非識別。我很好奇他們在做聯接時有什麼表現差異?
感謝
我只是將一些外鍵添加到我的數據庫中,並且通常我的所有外鍵都不識別,因爲我從來沒有打擾過讓他們識別,因爲我從來不知道它們的差別和我的數據庫總是對我來說似乎工作得很好。外鍵識別與非識別關係之間的性能差異
現在我已經決定我要正確創建這個數據庫並且正在使外鍵識別和非識別。我很好奇他們在做聯接時有什麼表現差異?
感謝
是的,可能會有一些性能優勢,通過使上確定關係的外鍵連接。但它取決於查詢(因爲優化方法總是這樣做)。
例如,查詢給定作者的書籍:
SELECT a.author_name, b.book_name
FROM Authors AS a
JOIN AuthorBooks AS ab ON a.author_id = ab.author_id
JOIN Books AS b ON b.book_id = ab.book_id
WHERE a.author_id = 12345;
在這種情況下,我們希望加入到AuthorBooks使用索引。它將使用哪個索引?這取決於我們如何在該表中定義索引。
這兩個實體表非常簡單。
CREATE TABLE Authors (
author_id INT AUTO_INCREMENT PRIMARY KEY,
author_name VARCHAR(50)
);
CREATE TABLE Books (
book_id INT AUTO_INCREMENT PRIMARY KEY,
book_name VARCHAR(50)
);
但是開發人員設計多對多表格有兩種常見方式。其中一個主鍵爲自動遞增ID:
CREATE TABLE AuthorBooks (
id INT AUTO_INCREMENT PRIMARY KEY,
author_id INT NOT NULL,
book_id INT NOT NULL,
FOREIGN KEY (author_id) REFERENCES Authors (author_id)
FOREIGN KEY (book_id) REFERENCES Books (book_id)
);
另一個沒有ID。主鍵是兩個外鍵的組合,這使得它們都具有識別關係及其相應的引用實體表。
CREATE TABLE AuthorBooks (
author_id INT NOT NULL,
book_id INT NOT NULL,
PRIMARY KEY (author_id, book_id),
FOREIGN KEY (author_id) REFERENCES Authors (author_id)
FOREIGN KEY (book_id) REFERENCES Books (book_id)
);
在性能方面有什麼區別?
首先,請記住MySQL如何爲外鍵實現索引:如果沒有索引,外鍵將隱式創建一個索引。如果列上已有索引,則外鍵將使用它。即使是包含外鍵列作爲最左列的索引,也可以使用該索引,並且不需要爲外鍵創建新索引。
在第一個AuthorBooks表設計中,由於MySQL從Authors到AuthorBooks進行連接,因此它在索引中查找author_id外鍵的條目。但要執行第二次連接,該索引條目必須獲取其引用的行,以獲取book_id值,然後將其用於連接到Books表。所以連接最終需要額外的查表。
在第二個AuthorBooks表設計中,author_id由表的PRIMARY KEY索引。因此,當聯接對author_id進行查找時,它可以訪問匹配的book_id,而無需對錶進行額外查找。 book_id可以用於第二次加入。這消除了查詢找到的每一行的步驟。
事實證明這對性能有很大的好處。我簡單地通過使多對多表使用像這樣的覆蓋索引來優化一些查詢 - 無論是通過使用主鍵還是在兩個外鍵上創建額外的兩列索引 - 這導致多達六個訂單性能的提高幅度。
@billKarwin的回答非常好。我只想添加一個觀察。
識別和非識別關係是邏輯結構。他們對潛在的業務領域進行建模 - 參見this question(也被無處不在的@billKarwin回答)。像這樣使用邏輯結構的原因是爲了使數據庫更容易理解(並因此保持,擴展等)。這是而不是使您的數據庫「更快」。
我同意這一點! –
最後,這是真正重要的大問題。那麼有人嗎? – danger89