為什麼導入 MySQL 轉儲會導致如此多的 I/O?
我導入了 100 個 SQL 格式的轉儲文件。總大小為 20 GB。導入後生成的 .ibd 文件的總大小為 40 GB。mysqld.exe 在磁碟上寫入 1.1 TB 並讀取 120 GB。為什麼會有這麼多 I/O?
我使用 MySQL Workbench 的預設選項來創建 SQL 格式的轉儲文件,即:
*它似乎與 MySQL 參考手冊的 InnoDB 表的批量數據載入*部分的建議非常吻合(除了
autocommit=0
,它不在我的轉儲中)。轉儲中生成的程式碼標題如下所示:/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; /*!40101 SET NAMES utf8 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; -- -- Table structure for table `askbot_activityauditstatus` -- LOCK TABLES `askbot_activityauditstatus` WRITE; /*!40000 ALTER TABLE `askbot_activityauditstatus` DISABLE KEYS */; INSERT INTO `askbot_activityauditstatus` VALUES etc
我知道我可以嘗試使用其他轉儲工具來加快速度,但我很好奇。寫的數量給我留下了特別深刻的印象。
我使用 Windows 7 SP1 x64、MySQL 5.6 和 MySQL Workbench 6.0。
從根本上說,恢復轉儲文件涉及插入所有行並為所有數據建構所有索引。鑑於此,轉儲文件的生成方式、您是否使用一個或多個文件、或者您選擇了哪些可用選項(儘管其中一些
extended-insert
可能會使未選擇的情況變得更糟)都不是特別相關。當您恢復文件時,您還:
- 將數據寫入事務日誌
- 將數據寫入雙寫緩衝區
- 將數據寫入表空間文件
- 將索引寫入雙寫緩衝區
- 將索引寫入表空間文件
- 如果啟用,則將數據寫入二進制日誌……並且如果您具有
binlog_format
“語句”的預設設置,那麼您實際上是在寫入轉儲文件中的幾乎每個字節加上成本……但是如果您binlog_format
設置為“行”,您正在為二進制日誌編寫更緊湊的版本……如果您binlog_format
設置為“混合”,那麼二進制日誌中實際使用的格式取決於您的預設事務隔離級別。設置innodb_flush_log_at_trx_commit從非常昂貴但符合 ACID 的預設值 1 到稍微不太安全的值 2 或明顯不太安全的值 0 肯定會加快您的插入速度,儘管它不太可能減少實際的 I/O,因為該值不會更改寫入事務日誌的內容,它只會更改 InnoDB 堅持要求作業系統確認日誌內容已保存到磁碟的頻率。如果在值設置為 2 或 0 期間發生崩潰,我在安全意義上使用“安全”,以防止最近的交易失去;1 防止 MySQL 或系統崩潰時的數據失去;如果 MySQL 崩潰而不是系統崩潰,2 可以防止數據失去,0 也不能防止。一旦你把它放回去,它就沒有任何後遺症。
快速旁注,顯示的一些看起來像評論的東西不是評論。/*!mnnrr 格式是 MySQL 向後兼容擴展,它告訴伺服器“如果您是 MySQL 版本 m.nn.rr 或更高版本,請執行此語句,否則忽略。”
/*!40000 ALTER TABLE `table_name` DISABLE KEYS */; /*!40000 ALTER TABLE `table_name` ENABLE KEYS */;
每個表都在轉儲文件中被這些包圍。這些對 MyISAM 比對 InnoDB 更有用,因為
DISABLE KEYS
指示儲存引擎在發布之前不要更新任何非唯一索引ENABLE KEYS
,允許寫入所有行數據,然後批量索引。使用 InnoDB,索引是在處理插入時建構的……所以當索引樹正在建構和洗牌時,那裡有很多 I/O 潛力。InnoDB 緩衝池的大小將在磁碟 I/O 量中發揮作用——如果它相對較小,可能會很重要——因為任何不能留在記憶體中的東西都必須立即刷新到磁碟, 僅在再次需要時才被讀回,這對於索引尤其如此,對於實際行來說更是如此,因為在 InnoDB 中,行以主鍵順序物理儲存,並以主鍵
mysqldump
將它們寫入文件順序…所以它們按照它們將被儲存的順序插入…但是二級索引必須來回穿梭到磁碟,因為索引頁隨著給定表上的插入操作的進行而更新.因此,由於所有不同的日誌記錄、安全性和 ACID 機制,每次插入都有一個“額外”活動的基線……而且索引似乎是可能創建大量額外 I/O 的萬用字元候選者。