MyISAM插入快的本质是省略事务日志、行锁、MVCC等ACID保障机制,仅追加数据到.MYD文件并更新.MYI索引;而InnoDB可通过调优参数(如关闭唯一性检查、调整刷盘策略、预排序主键)大幅提升批量导入速度。

MyISAM插入快的本质是“省略”而非“优化”
它快,是因为跳过了InnoDB必须做的几件事:事务日志写入、行锁管理、MVCC版本链维护、唯一性实时校验、聚簇索引页分裂处理。这些不是InnoDB“慢”,而是它为保证ACID和并发安全必须付出的成本。INSERT对MyISAM来说就是追加一行到.MYD文件末尾,再更新.MYI索引——没有redo log刷盘,没有buffer pool脏页刷回,也没有事务提交开销。
常见错误现象:Lock wait timeout exceeded在MyISAM里几乎不会出现(因为表锁直接排队),但并发写入时所有INSERT都会卡在同一个表锁上;mysqld崩溃后.MYD文件可能处于半写状态,REPAIR TABLE不一定能救回来。
- MyISAM的
COUNT(*)是元数据直读,O(1);InnoDB每次都要扫主键索引树判断可见性 - MyISAM不校验外键、唯一索引,导入前也不需要
DISABLE KEYS(它有效);InnoDB无视该指令 - MyISAM索引与数据分离,插入不触发页分裂;InnoDB聚簇索引要求主键有序,乱序写入会频繁分裂B+树页
InnoDB批量导入慢的真正瓶颈不在引擎本身
默认配置是为高一致性、小事务设计的,不是为LOAD DATA INFILE或百万级INSERT准备的。只要临时调整几个关键参数,InnoDB导入速度可以逼近MyISAM,且不牺牲崩溃恢复能力。
实操建议:
- 导入前执行:
SET unique_checks = 0、SET foreign_key_checks = 0(仅限可信数据源) - 调
innodb_flush_log_at_trx_commit从1改为2(掉电可能丢1秒日志,导入完成立即改回) - 用
ORDER BY primary_key预排序源数据,避免主键无序导致的页分裂 -
innodb_buffer_pool_size至少设为待导入数据体积的50%,否则频繁换页拖慢速度
LOAD DATA INFILE才是批量导入的事实标准
无论MyISAM还是InnoDB,LOAD DATA INFILE都比手写INSERT快5–20倍——它绕过SQL解析、权限检查、单行事务封装,走的是C API级数据通道。
注意几个硬性约束:
- 文件必须放在MySQL服务端,路径用绝对路径,如
/var/lib/mysql-files/data.csv - 先查
secure_file_priv值,文件必须放在此目录下,否则报错ERROR 1290 (HY000) - 字段分隔符和换行符要显式指定:
FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n',避免CSV引号嵌套解析失败 - InnoDB不支持
DISABLE KEYS,但MyISAM支持——别在InnoDB表上白费这一步
MyISAM快的代价在导入之后才真正显现
导入完成那一刻,MyISAM的“优势”就开始反噬:表级锁让后续任何SELECT或UPDATE都得排队;崩溃后无法自动恢复;OPTIMIZE TABLE锁表数小时;超过5000万行后.MYI索引文件严重碎片化。
真实业务里,导入只是起点。如果你的表接下来要被高频查询、被其他服务并发更新、要支撑在线报表或实时统计,MyISAM的纸面速度毫无意义。InnoDB的调优项都是可逆的、临时的,而MyISAM的设计缺陷是固化的——它不是“快一点”的选项,而是“放弃一部分能力换来的快”。


















