正常。Navicat 默认用 mysqldump 导出 SQL 文本,非二进制压缩,100MB 表导出达 300–500MB 属文本膨胀常态,主因是每行转 INSERT、字符串转义、时间/JSON/长文本完整展开及扩展插入格式开销。
导出文件比 information_schema.TABLES 显示的数据大很多,正常吗
正常。navicat 默认用 mysqldump 导出,它输出的是可重放的 sql 文本,不是二进制压缩格式。一个 100mb 的 innodb 表,导出后常达 300–500mb,原因不在 navicat,而在 sql 文本本身的膨胀特性。
mysqldump 为什么会把索引也“写成 SQL”
它不导出索引文件,而是导出 CREATE INDEX 或 KEY 子句。但真正导致体积暴涨的是:每行数据都变成一条 INSERT INTO ... VALUES (...) 语句;字符串字段带引号和转义;时间戳、JSON、长文本字段被完整展开;默认启用 --extended-insert(多值 INSERT),虽减少语句数,但换行和括号仍占空间。
- 禁用扩展插入:
--skip-extended-insert会让每行一个INSERT,文件更大,但更易调试和部分恢复 - 跳过索引重建:
--skip-add-drop-table --skip-create-options --skip-triggers --skip-routines可砍掉 20–40% 体积(如果你只关心主键+数据) - 注意:
--no-create-info会连建表语句都不要,还原时需手动建表
碎片空间是否会被 mysqldump 一并导出
不会。mysqldump 读的是逻辑数据,不是物理页。即使表有 60% 碎片率(Data_free 很高),导出内容只含实际存储的行记录,不会把空闲页、未分配空间或填充字节写进去。你看到的“备份文件大”,99% 来自文本编码开销,而非碎片。
- 验证方法:执行
SELECT table_name, data_length, index_length, data_free FROM information_schema.TABLES WHERE table_schema = 'your_db';,对比data_length + index_length和导出文件大小,前者是真实数据量,后者是文本表达量 - 如果
data_free异常高(比如 > 表总大小 30%),该优化表了,但优化不影响导出体积 - 别用
OPTIMIZE TABLE来“缩小备份文件”——它只减少运行时 I/O,对 dump 输出无影响
真正该关注的体积异常点
当导出文件远超预期(比如 1GB 原始数据导出为 8GB SQL),问题往往不在文本膨胀,而在隐式复制或冗余导出:
- 误勾了「包含事件/存储过程/函数」且库内有大量注释或长定义体,单个
PROCEDURE就可能占几 MB - 导出了
mysql系统库或 performance_schema —— 它们不含业务数据,但定义极多,mysqldump默认不跳过 - 表中存在
TEXT/MEDIUMTEXT字段,且内容含大量换行、缩进、HTML 或 Base64,这些在 SQL 中全被转义保留 - Navicat 在「高级」里开了「压缩备份文件」,结果用低效 ZIP 压缩纯文本,反而让最终文件变大(文本本身已高度可压缩,再套一层 ZIP 常增 5–10%)
导出前先跑一次 SELECT table_name, round((data_length + index_length)/1024/1024, 0) AS mb FROM information_schema.TABLES WHERE table_schema = 'your_db' ORDER BY mb DESC LIMIT 10;,心里有数再动手。体积大不可怕,可怕的是没搞清大在哪一环。











