搞定面试官 - 为什么在 MySQL 中使用 Delete 删除数据之后,表数据文件大小为什么没变?

嗯……到2 02 2 年再想吧。
在MySQL中,如果使用Delete删除数据,表的文件大小不会减少。
为什么?主要是因为InnoDB引擎。

想想看,InnoDB不太擅长直接从硬盘删除数据。
你做什么工作?它记下要删除的数据行及其在索引中的位置,打上复选标记,然后说:“嘿,这个东西已被删除。
”但物理上,它占用了磁盘空间并且没有移动。

想一想,你为什么要这样做?只是为了速度!如果每次删除数据都必须从硬盘中删除,硬盘就会异常繁忙。
向硬盘写入数据比读取数据慢得多。
所以InnoDB是聪明的。
它不会删除它,它只是标记它并留下一个位置。
当后面有新数据要插入时,恰好该位置为空,或者索引中的位置匹配,新数据就可以直接填充到那里,省力!
就是这样,被删除的数据被标记了,但并没有真正消失,只是占用了空间。
因此,表文件大小保持不变。
这与聚集索引无关,主要是出于性能考虑。
想想如果硬盘频繁移动的话,速度会有多慢。

如果确实想回收占用的空间,让表文件变小,该怎么办?您需要重建构建表。
只需使用命令 ALTER TABLE your_table ENGINE=InnoDB。
它将创建一个新表,将旧表中的所有数据移入其中,重新排列,然后删除旧表。
当我们搬到那里时,标记为“可重复使用”的区域确实被清理干净并恢复了空间。

但是请注意,早些时候,比如2 02 2 年,如果MySQL版本低于5 .6 ,这个操作不是“在线”的。
也就是说,重建表时,表必须暂停,不能插入或修改数据。
从5 .6 开始,有了在线支持,创建表时仍然可以正常使用。

简单来说,这就是InnoDB的原理。
为了速度,不要立即删除,而是标记它。
如果你想要空间,你必须重建表。
就是这样。

mysql表的data free过大

1 .由于结构变化未释放空间:OPTIMIZED表名,释放空间。
2 .频繁的增删操作:ANALYZABLE表名减少碎片。
3 .索引扩展:删除或重建碎片索引以优化空间。
4 . 统计信息不准确:ANALYSETABLE更新统计信息以修复潜在问题。
5 、自己掂量一下。

MySQL的delete操作与数据库空间

说实话,MySQL的删除功能很有趣。
刚进来的时候我很困惑。
想一想,为什么还会出现记录删除的情况呢?其实这背后有一个很现实的考虑。

当我构建电子商务系统时,用户报告数据库空间不断增加。
检查了半天,发现后台疯狂删除无效命令,表空间并没有减少。
当时我很困惑。
从逻辑上讲,如果我删除了一条记录,我就必须将其归还,对吗?经过查资料,我发现MySQL操作是故意设计的——它不会立即将位置返回给你。
看吧,执行删除命令时,MySQL实际上是在记录上画了一个“已删除”的标记,相当于给垃圾转储打了一个标签,但转储站点还没有被清理干净。
这样的设计是出于性能考虑。
如果每次删除记录时都恢复空间,数据库响应时间会慢多少?我尝试在百万级表上运行删除,并且表大小保持不变,除非您使用表大小调整。
有趣的是,这种空间浪费在 MISAM 引擎中尤其明显,因为它依赖于表级锁。
我当时在做一个项目,由于反复删除而不清理,办公桌空间最终扩大到原来的大小一倍。
后来改用InnoDB后,情况就好多了。
虽然 InnoDB 会减慢清理速度,但它使用行级锁并且影响较小。

我有一个朋友,我曾与他分享过惨痛的教训。
如果1 =1 ,则对表进行删除,发现空间没有减少。
当时他想“直接删除测试表”,但他们忘了支持他,最后他不得不使用drop来重建它——这个操作,兄弟,是不可逆的。
truncate虽然删除了所有数据,但它直接重置了表结构,并且可以立即访问其位置。
我测试了一个1 0万行的数据表,截断的速度是删除的两倍。

我也曾踩过便利的陷阱。
我曾经使用过OPTIMIZE TABLE,结果是线上业务被锁了好几天。
后来我意识到这种程序应该在早上进行调整。
我记得当运行 OPTIMIZE TABLE phpernote_article 时,整个数据库的 CPU 增加到 9 0% 并且所有我记得后台作业被阻止了。
所以现在我们使用脚本先备份并在生产环境中执行。
总结一下?使用删除时,您应该注意它仅用于标记。
不要指望删除记录后空间会自动减少。
如果空间紧张,可以考虑OPTIMIZE,但这取决于时间和引擎。
如果确实想清除表,请根据情况选择删除(恢复)或截断(快速但不可恢复)。
这堂课让我终生难忘。

MySQL 清空表后查询大小仍不变?原因和解决办法

原因:统计数据滞后 解决方案:可解析表名;
原因:物理空间未释放 解决方案:截断表名;
检查InnoDB配置:将变量显示为'innodb_file_per_table';