2011-11-15 95 views
0

每個成員有0個或更多的訂單。每個訂單至少包含1個項目。 memberid - varchar,不是整數 - 沒關係(請不要提及這不是很好,我不能改變它)。 所以,thera 3表:成員,訂單和order_items。訂單和ORDER_ITEMS低於:MySQL:無主鍵優化表(索引,外鍵)

CREATE TABLE `orders` (
`orderid` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, 
`memberid` VARCHAR(20), 
`Time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP , 
`info` VARCHAR(3200) NULL , 
PRIMARY KEY (orderid) , 
FOREIGN KEY (memberid) REFERENCES members(memberid) 
) ENGINE = InnoDB; 


CREATE TABLE `order_items` (
`orderid` INT(11) UNSIGNED NOT NULL, 
`item_number_in_cart` tinyint(1) NOT NULL , --- 5 items in cart= 5 rows 
`price` DECIMAL (6,2) NOT NULL, 
FOREIGN KEY (orderid) REFERENCES orders(orderid) 
) ENGINE = InnoDB; 

所以,ORDER_ITEMS表如下所示:

的OrderID - item_number_in_cart - 價格:

...

1000456 - 1 - 24.99

1000456 - 2 - 39.99

1000456 - 3 - 4.99

1000456 - 4 - 17.97

1000457 - 1 - 20.00

1000458 - 1 - 99.99

1000459 - 1 - 2.99

1000459 - 2 - 69.99

1000460 - 1 - 4.99

...

正如你看到的,ORDER_ITEMS表沒有主鍵(我認爲這是沒有意義的創建此表的AUTO_INCREMENT ID,因爲一旦我們要提取數據,我們隨時提取作爲WHERE orderid='1000456' order by item_number_in_card asc - 整個塊,身份證無助於查詢)。 一旦數據被插入到order_items中,它就不會被UPDATE,只是被選中。

的問題是:

  • 我認爲這是把指數item_number_in_cart一個好主意。有人可以證實嗎?
  • 還有什麼我必須做order_items來提高性能,或者看起來相當不錯?我可能會錯過一些東西,因爲我是一個新手。

在此先感謝您。

+0

「order_items」沒有數量字段嗎,或者您是否忽略列來簡化示例? – outis

+0

感謝您的問題。是的,我刪除了幾行。當選擇或插入價格時,選擇並插入它們,然後才選擇它們。 – Haradzieniec

+0

你的意思是你刪除了幾列? – outis

回答

1

主鍵可以跨越多個列。你不能使用的列PRIMARY屬性要做到這一點,但你可以定義多個列單獨的主鍵:

CREATE TABLE `order_items` (
    `orderid` INT(11) UNSIGNED NOT NULL, 
    `item_number_in_cart` tinyint(1) NOT NULL , --- 5 items in cart= 5 rows 
    `price` DECIMAL (6,2) NOT NULL, 
    PRIMARY KEY (orderid, item_number_in_cart), 
    FOREIGN KEY (orderid) REFERENCES orders(orderid) 
) ENGINE = InnoDB; 

此外,主鍵只是一個唯一的鍵,每一個列不爲空與某個名字;您可以在不可爲空的列上創建自己的唯一鍵以獲得相同的效果。

通過索引item_number_in_cart,您不太可能獲得很大的性能提升;由於給定訂單的訂單項數量往往很小,因此按item_number_in_cart排序不會佔用太多時間或記憶。但是,在主鍵中包含列將有助於數據的一致性。

+0

我不確定在檢查問題解決後我可以問一個問題,但是......在我聲明(orderid,item_number_in_cart)作爲主鍵之後,它也會被索引。它不能減少,但不增加性能? MySQL會自動索引這個主鍵,但我絕對不會選擇「WHERE orderid ='1234567'和item_number_in_cart ='3'」的任何查詢,只能通過「item_number_in_cart asc」的WHERE orderid ='1234567'命令。所以,它不可能是無用的甚至更糟糕的 - 聲明PRIMARY KEY(orderid,item_number_in_cart)? – Haradzieniec

+0

@Haradzieniec:如果你有更多的問題站在他們自己的優點,你可以張貼他們作爲新的問題。 「指數何時能夠降低MySQL的性能?」這是一個公平的問題,儘管之前可能已經提出過。如果問題是你已經問過的問題的擴展,你可以編輯你的問題(「何時(如果有的話)將索引'item_number_in_cart'降低性能?」可能是你的第一個問題的延伸)。編輯時應注意使現有答案無效,如果您原來的問題陳述結果不準確或不準確,則這是完全可以接受的。 – outis

1

item_number_in_cart上的索引將不會被使用。這是微小的int,沒有足夠的選擇性,一旦你有2條記錄,甚至不會被引擎考慮。您可以將其作爲第二列添加到orderid上的現有索引(因爲您在orderid上創建了FK約束,mysql自動在此字段上添加索引)。
你說數據在order_items從未更新,但我認爲它可以被刪除;沒有主鍵這樣做會有問題。

+0

「您可以將其作爲第二列添加到orderid上的現有索引」 - whad是否意味着 - 「將其作爲第二列添加到現有索引」? – Haradzieniec

+0

正如Outis在他的回答中所做的那樣(PRIMARY KEY(orderid,item_number_in_cart),) 這引起了您關於性能的額外問題。 –

1

不管怎麼說,我會有一個autoinc,因爲我是代理鍵的一個大信徒,但正如alex07所建議的一個索引,甚至orderid的主鍵,item_number_in_cart應該把事情弄清楚。請注意item_number的順序將使用兩次排序(獲取數據,然後按數字順序排序),因此索引/鍵將直接截斷,因此您希望該索引甚至可以使用代理鍵。