2017-03-02 49 views
1

我創造了這個表:爲什麼這個組合鍵沒有索引?

CREATE TABLE incident_originator (
    id_incident INT (11) UNSIGNED NOT NULL, 
    id_user INT (11) NOT NULL, 
    PRIMARY KEY (
     id_incident, 
     id_user 
    ), 
    CONSTRAINT fk_incident_incident_originator FOREIGN KEY (id_incident) REFERENCES incident_table (id_incident) ON DELETE RESTRICT ON UPDATE CASCADE, 
    CONSTRAINT fk_user_incident_originator FOREIGN KEY (id_user) REFERENCES users (id_user) ON DELETE RESTRICT ON UPDATE CASCADE 
) ENGINE = INNODB DEFAULT CHARSET = latin1; 

然而,fk_user_incident_originator,被索引,並且fk_incident_incident_originator不是。這是爲什麼? InnoBD是不是應該自動索引所有外鍵?缺少id_incident中的索引會使連接速度變慢,對嗎?我讀得越多,理解得越少...

另外,當我向表中添加值時,它們按第二列排序,它變得奇怪,以讀爲人。

編輯:當我做了SHOW INDEX FROM incident_originator;它返回:

Non_unique Key_name Seq_in_index Column_name 
0 PRIMARY 1 id_incident 
0 PRIMARY 2 id_user 
1 fk_user_incident_originator 1 id_user 

回答

1

fk_incident_incident_originator

當然是。

PRIMARY KEY (id_incident,id_user), 

在引用表中,必須有在外國鍵列在同一順序的第一列的索引。如果索引表不存在,則會在引用表上自動創建這樣的索引。

https://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html

id_incident是第一個(意爲最左側)的主鍵列...和主鍵是強制執行的約束時查找值一個非常好的指標。添加第二個索引將是多餘的。

連接也是如此(儘管連接並不是外鍵總是編入索引的實際原因) - 任何索引都包含錨定在索引左側的所有連接列,這對連接非常有效。

它們按第二列排序,它變得奇怪,以讀爲人。

告訴任何人,你知道數據庫沒有爲人類的利益命令它的輸出,除非人類使用ORDER BY。根據定義,沒有ORDER BY的結果集是無序的。行通常以主鍵順序返回的事實是巧合,而不是設計或必要性。當表格變大時,此行爲可能會發生變化,因爲優化程序在讀取表時會更改策略...但由於id_user上的索引實際上是覆蓋索引(它包含表中的所有列,因爲所有索引還包含副本主鍵......或者更確切地說,它包含滿足這個特定查詢所需的所有列 - 這些有時候是兩個不同的東西,這是不在實際代碼中使用SELECT *的最好理由之一)所以優化器恰好選擇它作爲其源。它從它選擇的任何索引讀取索引順序的行,並且該順序變成完全重合的結果順序。

+0

我增加了結果的'SHOW INDEX'的問題,因爲我沒有看到,就像你說的,那'fk_incident_incident_originator'索引。不應該顯示在「SHOW INDEX」結果中嗎? 關於這個 >它從它選擇的任何索引讀取索引順序的行,並且該順序變成完全重合的結果順序。 PRIMARY鍵和Seq_in_index值的索引順序表明它應該先按id_incident排序列,不是嗎? 無論如何,我不會使用'SELECT *'或不要求查詢的結果,訂單的東西更多的是好奇心。 – Tyrannogina

+0

「SHOW INDEX」令人困惑的原因是因爲在那裏,「fk_user_incident_originator」並不意味着你認爲它的意思。這是索引名稱,它只是巧合地與約束符號相同。如果你首先向user_id添加了一個索引,然後添加了這個外鍵,那麼它也不會在'SHOW INDEX'中顯示出來。 –

相關問題