2011-07-21 74 views
16

我有一個表,我主要做的更新,我想知道,如果更新查詢,將有助於對其中列和更新的列或只是其中一個索引列有索引中受益?mysql更新查詢是否受益於索引?

+2

'WHERE'列中的索引將(可能)幫助。可能意味着它會幫助它,如果它會幫助等效的'SELECT'。例如,如果你有'WHERE id> 3'條件並且幾乎所有的id都是> 3,那麼索引就不會被使用。 –

+0

關於問題的第二部分,'(wherecolumn,updatedcolumn)'上的索引也可能有幫助。但我認爲只是因爲MySQL檢查並沒有更新更新的值與列的現有值相同。因此,如果有很多行,grp = 47,a已經等於7,'UPDATE t SET a = 7 WHERE GRP = 47'可能會有利於形成'(grp,a)'索引。 –

+0

您正在使用什麼存儲引擎?表的結構是什麼?更新查詢是什麼?這些都可以對答案產生影響。 – Mike

回答

13

剛上where列。更新列上的索引實際上會降低查詢速度,因爲索引必須隨數據一起更新。 where列的索引將加速更新,並選擇,但減慢一些插入。

指數也造成開銷,當你刪除行。一般來說,它們是一件好事,雖然在很多列上你使用的是WHERE,並且它們基本上在你要加入的列上是必需的,或者ORDER BY

+1

更新索引完全是在內存中完成的,速度非常快。更新查詢是一個只增加一列的查詢。我想知道是否將第二列添加到索引將省略額外的讀取來查找原始值。 – incognito2

+0

這是一個很好的問題。我認爲MySQL優化器會利用索引,但很難說。你總是可以打開分析並嘗試兩個查詢,看看你是否注意到任何事情。 – Paulpro

7

對於這一列來說不是一個簡單的答案。所以在這裏。

UPDATE table SET ColumnA = 'something' 

如果ColumnA存在索引,那麼你將有輕微的性能損失,因爲會爲每一行兩次寫操作。首先是表中的數據,然後寫入索引更新。
甚至可以有多個索引,每個索引都有ColumnA作爲索引的一部分,這意味着除了表格行以外,您還會有幾次寫入。您可以看到有多少個索引可以開始真正減慢更新速度。
但是,如果ColumnA根本沒有被編入索引,那麼它將只針對每一行進行一次寫入。

UPDATE table SET ColumnA = 'something' WHERE ColumnB = 'something else' 

對於一個索引是否存在對ColumnB而不是ColumnA,這將是非常快的定位記錄此查詢(稱爲搜索)和一個寫更新,並作爲指數不關心關於columnA,它不會需要更新。
但是,如果您索引ColumnA而不是ColumnB,則會先讀取表中的每一行(稱爲掃描,通常是壞事),雖然讀取速度比寫入速度還要慢,但它會寫入表,然後再寫入索引。基本上是最慢的做事方式。

DELETE table WHERE ColumnB = 'somethingelse' 

現在,如果你在這個表中的兩個寫有任何列的索引,從表和更新刪除/索引記錄的刪除。
再次,如果ColumnB未被索引,您將掃描該表,然後刪除表中的行並更新索引(如果有)。

INSERT INTO table (ColumnA, ColumnB) VALUES ('something','something else') 

如果沒有索引存在,那麼只需寫一次表就可以了。
同樣,如果索引確實存在,則爲每個索引額外寫入。

我沒有提到的主鍵唯一約束,因爲你真的不能讓身邊,當你需要一個主鍵,但每個記錄必須檢查看看是否有已經在插入之前鍵存在。這將是一個快速的主要關鍵指標尋求,但是,在這個過程中又是一個步驟。步驟越少,速度越快。

現在回到你的,基本上,如果你需要更新一個特定的記錄,索引將幫助你找到記錄比掃描整個表要快。查找記錄所節省的時間將遠遠超過更新索引時丟失的時間。如果你只是插入而不讀,那麼索引會減慢你的速度。它成爲一個平衡的東西。如果你需要閱讀特定的記錄,那麼索引將非常有幫助。但是,索引越多,寫入越慢。

+0

你在回答中提到哪個存儲引擎? – Mike

+0

這裏是最佳答案。謝謝! –

12

這裏大多數人不知道索引在MySQL中是如何工作的。

這取決於您正在使用的存儲引擎。 InnoDB使用完全不同於MyISAM的索引。這是因爲MySQL在存儲引擎級別上執行索引而不是MySQL服務器級別。

恐怕大多數人在這裏給你的答案是基於其他數據庫,其中索引以不同的方式從MySQL工作到

InnoDB的

InnoDB的情況。這是因爲每當在InnoDB中更新一行時,索引也必須更新,因爲InnoDB's索引必須是連續的,所以它必須找出它應該在哪個索引中並插入其中的哪個頁節點。有時特定頁面可能已滿,所以它必須拆分頁面,浪費空間並增加時間。無論您索引哪個列,都會發生這種情況,因爲InnoDB使用聚簇索引,索引存儲整行的數據。

的MyISAM

在MyISAM數據的情況下,不存在這個問題。 MyISAM實際上只使用1列索引,即使您可以在多於1列上設置多個唯一身份碼。另外MyISAM's索引不是按順序存儲的,所以更新非常快。同樣插入也很快,因爲MyISAM只是將它插入行的末尾。

結論

所以對於你的問題,你應該考慮的,而不是擔心查詢是否會使用索引模式設計。如果您主要在桌面上更新,我建議您不要使用InnoDB,除非您需要行級鎖定,高併發性和事務。否則MyISAM會更好的更新任務。如果您使用的是InnoDB索引,則不會真正幫助更新,尤其是在表格非常大的情況下。

+0

如果不使用事務,如果在更新期間服務器崩潰,您將如何處理MyISAM表中的數據損壞?這對於更新是主要操作的表格可能很重要。 – Mike

+0

你可以使用'CHECK TABLE tablename'和'REPAIR TABLE tablename'或'myisamchk'。通常情況下,這不是除了崩潰後丟失的時間之外的問題。相反,InnoDB索引很容易碎片化,不能像其他存儲引擎那樣使用'ALTER TABLE innodbtable ENGINE = InnoDB'修​​復。 所以這真的取決於你的情況。 –

+0

如果在發生崩潰時正在進行更新,是否可以通過MyISAM表破壞數據完整性 - 取決於正在執行的更新,可能很難判斷哪些記錄已更新,哪些還沒有更新?至於索引碎片,它可以通過ALTER TABLE tbl_name ENGINE修復[docs state](http://dev.mysql.com/doc/refman/5.5/en/innodb-file-defragmenting.html) = INNODB'。我錯過了什麼嗎?無論如何,我要在這裏談論題目,我同意這取決於情況。但數據完整性是一個重要考慮因素。 – Mike