2013-04-12 147 views
0

最近,我發現其中一臺服務器在磁盤上有很高的I/O流量。由於某些診斷後在某個表上寫入索引而導致的高I/O。我已經做了幾次評估測試,發現在將記錄插入到索引較大的表中時,mysql會佔用大量的寫入空間。大索引插入性能下降(MYSQL)

索引列的數據類型是VARCHAR(15)和varchar(17),兩者都是非唯一索引 僅存在80寫在磁盤上,如果我加載20000個記錄到具有10000條記錄,而有表1700在表增長到2000萬(在索引列上獲得大約1百萬個不同值)時在磁盤上寫入,即使插入的記錄數量相同。

引擎是MyISAM。

增加索引的大小也會增加每個插入磁盤的寫入次數。

它是BTREE指數的行爲,我該如何解決這個問題?

回答

3

使用InnoDB代替MyISAM。

InnoDB通過緩衝寫入二級索引的寫操作,如果可能的話合併它們,並延遲昂貴的I/O。您可以在Controlling InnoDB Change Buffering下的MySQL手冊中閱讀關於此功能的更多信息。


回覆您的評論:

插入一個新值到B樹可能是昂貴的。如果在葉級沒有空間,插入可能會導致分裂樹的非葉節點,可能一直到樹頂部的級聯效應。這可能會導致很多I/O,因爲樹中的不同節點可能在磁盤上彼此遠離存儲。

其他緩解策略是通過將少用的數據移動到另一個表來減小表。或者使用MySQL table partitioning來創建一個包含許多單獨物理表的邏輯表。每個這樣的子表必須具有相同的索引,但是然後每個單獨的索引將更小。


有一個動畫示例這裏: http://www.bluerwhite.org/btree/

看的例子的「插入鍵33到B樹(W /拆分)」,其中它顯示了插入值到B的步驟過度填充它的樹節點以及B樹做出的響應。

現在想象一下這個例子的例子只顯示了更深層的B-樹的底部(如果你的索引B-樹有數百萬個條目就是這種情況),填充父節點本身就可以一個溢出,並強制分割操作繼續樹中的較高級別。如果樹頂部的所有祖先節點都已經被填充,這可以一直延續到樹的最頂端。

+0

感謝您的回覆,是否有任何其他可能的方式來減少索引寫入的I/O,因爲表處於生產環境中,而不喜歡更改其引擎。另外,昂貴的I/O是BTREE的性質還是任何原因造成的。 – Holylai

+0

非常感謝您的明確解釋,這意味着當葉子節點發生溢出時,由於分割節點的操作導致的I/O,並且樹增長時花費太多?因爲我不是很懂B樹的算法,這種行爲追加到所有的RDBMS如ORACLE(儘管在緩衝I/O) – Holylai

+0

我知道了,感謝這麼多,但爲什麼主索引不會造成這樣的問題? – Holylai