2009-11-27 46 views
2

我正在使用現有的數據庫並嘗試優化它。我看到沒有單個主鍵的表,但有兩個外鍵用作主鍵。我知道它會起作用。然而,爲了獲得更好的性能,使用兩個外鍵的主鍵(key1,key2)能夠像單鍵一樣工作更好嗎?什麼是MySQL主鍵(key1,key2)

例如:

CREATE TABLE ABC (
    'xid' int(11), 
    'yid' int (11), 
PRIMAY KEY (xid, yid) 
) 

does it perform the same (in terms of indexing) as: 

CREATE TABLE ABC (
    'id' int(11), 
    'yid' int (11), 
    'xid', int (11), 
    PRIMARY KEY (id), 
KEY (xid, yid) 
) 

一些更新有

所以,我做了一些測試使用簡單的查詢,在三個不同的表

表妙..,有10000條記錄。只有userid作爲主要索引。

SELECT * FROM MYA其中userid = 12345

id select_type  table type possible_keys key  key_len  ref  rows Extra 
1 SIMPLE   myA const PRIMARY    PRIMARY 4 const 1 

表MYB,是一個多到許多表,與伯id和的userid兩個外鍵中的一個。超過50000記錄

SELECT * FROM MYB其中userid = 12345

id select_type  table type possible_keys key  key_len  ref  rows Extra 
1 SIMPLE   myB ref  userid   userid  4 const 53 

表MYC,也是許多一對多表,但與複合主鍵,用戶ID是兩個中的一個。超過10萬的記錄

SELECT * FROM MYC其中userid = 12345

id select_type  table type possible_keys key  key_len  ref  rows Extra 
1 SIMPLE   myC ALL  NULL    NULL NULL NULL 101289 Using where 

所以,表C中居然檢查所有10萬條記錄! (查詢只返回50條記錄)

有些東西我不明白......在我看來,複合材料主要是不做這項工作。


更多..

雖然我做更多的測試和「解釋」,我的結論是(在MySQL),即使你設置組合鍵作爲主鍵。您仍然必須爲所有鍵明確設置索引。然後你會喜歡索引。

回答

1

添加id列只有在向用戶公開內容時才值得。無論哪種方式,這是一個典型的多對多連接表。

要將主鍵更改爲單列意味着將唯一鍵約束添加到兩個外鍵列上 - 因爲您將列定義爲主鍵時獲得唯一性,即使它是組合鍵。組合鍵是2+列的組合。

如果您未選擇該id列,則不需要該列。

1

你所描述的是一個複合主鍵,它是可以接受的和合理的模式。當有一個完全可以接受的候選鍵時,許多應用程序使用人工主鍵(通常是int或guid)。這爲數據庫添加了工作,但在某些情況下使應用程序更易於編寫。

當已有候選人時,沒有真正的理由添加額外的主鍵。我傾向於不這樣做。

您還沒有加入不必要的自動生成的主鍵列獲得性能在某些情況下,它降低了數據庫的空間使用情況(雖然只是輕微)

4

在告訴你第二個例子中,xidyid索引但沒有什麼能阻止你的應用程序進入同一對xidyidABC表的多個行:

INSERT INTO ABC (xid, yid) VALUES (123, 456), (123, 456); -- NO ERROR 

您可以GE無意的重複這種方式,並且當你進行連接和計數時它可能會造成奇怪的效果。此外,如果您需要更新行以更改給定的xid和其yid之間的關聯,則可以更新一行而不更新其他行。

您至少應該將(xid, yid)的密鑰聲明爲UNIQUE KEY以防止重複。

您顯示的第一個示例使用複合主鍵(有人說複合主鍵)。 SQL支持多列索引和多列約束。這樣做沒有任何缺點,除了如果你想運行一個查詢來選擇一行,你需要使用兩列而不是一個標識行的條件。

DELETE FROM ABC WHERE xid = 123 AND yid = 456; 

同樣,如果另一個表包含外鍵引用ABC表,它必須有兩列。

有足夠的程序員發現使用兩列是如此繁重和混亂,他們寧願添加一列代理鍵。

當不需要任何東西時,堅持使用多餘的代理鍵是我認爲是SQL反模式的東西。


重新上述更新的問題:你知道,當你的搜索包括索引最左邊的列的複合索引不僅可以幫助?任何品牌的RDBMS中的任何複合索引都是如此。示例:

CREATE TABLE myC (
    somethingid INT, 
    userid  INT, 
    PRIMARY KEY (somethingid, userid) 
); 

SELECT * FROM myC WHERE userid = 12345; 

此查詢不能使用主鍵索引。

經典的例子來解釋複合索引的使用是電話簿比喻:如果我問你要搜索的每個人的姓氏是「托馬斯」你可以用事實電話簿按姓氏有序幫助快速進行搜索。但是如果我要求你搜索名字是「Thomas」的所有人,你必須搜索每一頁。電話簿就像是一個複合索引(last_namefirst_name)。所以如果你的搜索不包括last_name,你必須訴諸暴力搜索。

您也可以爲其他列創建額外的索引,因此您可以使用該索引作爲標準進行搜索。第一列不需要額外的單列索引。複合指數是足夠的。

CREATE TABLE myC (
    somethingid INT, 
    userid  INT, 
    PRIMARY KEY (somethingid, userid), 
    KEY (userid) 
); 

通常如果該列被聲明爲外鍵,則RDBMS 應該自動創建索引。但是,在某些RDBMS產品的某些版本中,您必須自己創建一個外鍵列的索引,作爲單獨的操作。

0

還有一個關於主鍵的很酷的事情,那就是數據實際上是由磁盤上的主鍵來排序的。因此,就性能而言,即使是唯一索引和主鍵之間也存在細微差別。雖然這可能不會有太大的性能差異,但實際上需要多少時間才能從磁盤中獲取數據。

相關問題