在 InnoDB 中,你的 delete 操作,并不会真的把数据删除,mysql 实际上只是给删除的数据打了个标记,标记为删除,因此你使用 delete 删除表中的数据,表文件在磁盘上所占空间不会变小,我们这里暂且称之为假删除。

上面这个是结论,我们可以通过一个例子来验证下。

沿用前面文章中的例子吧,先创建一个存储过程,插入 10w 条数据,然后看下这 10w 条数据占了多大的空间。

CREATE TABLE `t` (

`id` int(11) NOT NULL,

`a` int(11) DEFAULT NULL,

`b` int(11) DEFAULT NULL,

PRIMARY KEY (`id`),

KEY `a` (`a`),

KEY `b` (`b`)

) ENGINE=InnoDB;

#定义分割符号,mysql 默认分割符为分号;,这里定义为 //

#分隔符的作用主要是告诉 mysql 遇到下一个 // 符号即执行上面这一整段sql语句

delimiter //

#创建一个存储过程,并命名为 testData

create procedure testData()

#下面这段就是表示循环往表里插入10w条数据

begin

declare i int;

set i=1;

while(i<=100000)do

insert into t values(i, i, i);

set i=i+1;

end while;

end //  #这里遇到//符号,即执行上面一整段sql语句

delimiter ; #恢复mysql分隔符为;

call testData(); #调用存储过程

#下面这两条命令可以查看表文件所占空间大小

mysql> use information_schema;

Reading table information for completion of table and column names

You can turn off this feature to get a quicker startup with -A

Database changed

mysql> select concat(round(sum(DATA_LENGTH/1024/1024),2),'M') from tables where table_schema='test' AND table_name='t';

+-------------------------------------------------+

| concat(round(sum(DATA_LENGTH/1024/1024),2),'M') |

+-------------------------------------------------+

| 3.52M                                           |

+-------------------------------------------------+

1 row in set (0.04 sec)

可以看到 10w 条数据在 mysql 中占用了 3.52M 大小的空间,那么我们执行删除命令 delete from t,再看看呢。

#先删除表所有数据,再重新查看表文件大小

mysql> delete from t;

Query OK, 100000 rows affected (0.46 sec)

mysql> use information_schema;

Reading table information for completion of table and column names

You can turn off this feature to get a quicker startup with -A

Database changed

mysql> select concat(round(sum(DATA_LENGTH/1024/1024),2),'M') from tables where table_schema='test' AND table_name='t';

+-------------------------------------------------+

| concat(round(sum(DATA_LENGTH/1024/1024),2),'M') |

+-------------------------------------------------+

| 3.52M                                           |

+-------------------------------------------------+

1 row in set (0.00 sec)

从结果可以发现表数据被清空后,表所占空间大小并没有变化,这就验证了上面的结论,delete 操作并没有真正删除数据,表的空间并没有被释放。

这些被删除的记录行,只是被标记删除,是可以被复用的,下次有符合条件的记录是可以直接插入到这个被标记的位置的。

比如我们在 id 为 300-600 之间的记录中删除一条 id=500 的记录,这条记录就会被标记为删除,等下一次如果有一条 id=400 的记录要插入进来,那么就可以复用 id=500 被标记删除的位置,这种情况叫行记录复用。

还有一种情况是数据页复用,就是指整个数据页都被标记删除了,于是这整个数据页都可以被复用了,和行记录复用不同的是,数据页复用对要插入的数据几乎没有条件限制。

还以上面那个插入为例,假如要插入的记录是 id=1000,那么就不能复用 id=500 这个位置了,但如果有一整个数据页可复用的话,那么无论 id 值为多少都可以被复用在这个页上。

这些被标记删除的记录,其实就是一个空洞,有种占着茅坑不拉屎的感觉,浪费空间不说,还会影响查询效率。

因为你要知道,mysql 在底层是以数据页为单位来存储和读取数据的,每次向磁盘读一次数据就是读一个数据页,然而每访问一个数据页就对应一次磁盘 IO 操作,磁盘 IO 相对内存访问速度是相当慢的。

所以你想想,如果一个表上存在大量的数据空洞,原本只需一个数据页就保存的数据,由于被很多空洞占用了空间,不得不需要增加其他的数据页来保存数据,相应的,mysql 在查询相同数据的时候,就不得不增加磁盘 IO 操作,从而影响查询速度。

其实不仅仅是删除操作会造成数据空洞,插入和更新同样也会造成空洞,这里就不细说了,你知道就行。

因此,一个数据表在经过大量频繁的增删改之后,难免会产生数据空洞,浪费空间并影响查询效率,通常在生产环境中会直接表现为原本很快的查询会变得越来越慢。

对于这种情况,我们通常可以使用下面这个命令就能解决数据空洞问题。

optimize table t

这个命令的原理就是重建表,就是建立一个临时表 B,然后把表 A(存在数据空洞的表) 中的所有数据查询出来,接着把数据全部重新插入到临时表 B 中,最后再用临时表 B 替换表 A 即可,这就是重建表的过程。

我们再来试验一下,看看效果。

mysql> optimize table t;

+--------+----------+----------+-------------------------------------------------------------------+

| Table  | Op       | Msg_type | Msg_text                                                          |

+--------+----------+----------+-------------------------------------------------------------------+

| test.t | optimize | note     | Table does not support optimize, doing recreate + analyze instead |

| test.t | optimize | status   | OK                                                                |

+--------+----------+----------+-------------------------------------------------------------------+

2 rows in set (0.39 sec)

mysql> use information_schema;

Reading table information for completion of table and column names

You can turn off this feature to get a quicker startup with -A

Database changed

mysql> select concat(round(sum(DATA_LENGTH/1024/1024),2),'M') from tables where table_schema='test' AND table_name='t';

+-------------------------------------------------+

| concat(round(sum(DATA_LENGTH/1024/1024),2),'M') |

+-------------------------------------------------+

| 0.02M                                           |

+-------------------------------------------------+

1 row in set (0.00 sec)

可以看到表文件大小已经变成 0.02M了,说明表空间被释放了,这个 0.02M 应该是定义表结构文件的大小了。

另外下面这个命令也可以实现重建表,可以达到跟上面一样的效果,而且推荐大家使用下面这个命令,大家可以试试。

alter table t engine=InnoDB

注意本文内容是基于 InnoDB 引擎,对于其他引擎可能存在一些差异。原创不易,如果文章对你有启发,就点个在看吧,有疑问也可以在下面留言交流,也可以与我私信交流,感谢支持。

mysql不是实际删除_MySQL删除操作其实是假删除相关推荐

  1. mysql delete 标记_MySQL删除操作其实是假删除

    在 InnoDB 中,你的 delete 操作,并不会真的把数据删除,mysql 实际上只是给删除的数据打了个标记,标记为删除,因此你使用 delete 删除表中的数据,表文件在磁盘上所占空间不会变小 ...

  2. 表的插入、更新、删除、合并操作_17_按照条件删除表中记录

    按照条件删除表中记录 需求描述 需求:删除dept表里deptno为50的记录,但后期可通过数据库日志恢复. 解决方法:这里通过DELETE FROM TableName WHERE Columnam ...

  3. mysql delete 级联删除_MySQL 数据库表的 ondelete 级联删除

    首先,创建三个数据库表映射类 User .Course.Lab 外键关联不用说,两个一对多的关系,ForeignKey 都是一样的, 注意 Course 类和 Lab 类中 relationship ...

  4. mysql 语句怎样修饰约束_MySQL中的约束,添加约束,删除约束,以及一些其他修饰讲解...

    (1)创建数据库 CREATE DATABASES 数据库名; (2)选择数据库 USE 数据库名; (3)删除数据库 DROP DATAVBASE 数据库名; (4)创建表 CREATE TABLE ...

  5. mysql压缩包删除_mysql解压缩方式安装和彻底删除的方法图文详解

    一.安装mysql (1)将下载下来的mysql压缩文件解压缩到需要安装mysql的目录中 (2)打开解压后的文件夹,复制default.ini文件并重命名为my.ini,此文件的相关配置为: (3) ...

  6. mysql级联是什么意思_MySql级联操作

    转自:http://blog.csdn.net/codeforme/article/details/5539454 外键约束对子表的含义: 如果在父表中找不到候选键,则不允许在子表上进行insert/ ...

  7. mysql查询男生基本情况_MYSQL查询操作 详细

    学习目标 1 掌握select查询所有字段.指定字段的数据 2 掌握消除重复行命令distinct 3 掌握as给字段.表起别名 4 掌握条件查询where后跟比较运算符.逻辑运算符的用法 5 掌握条 ...

  8. mysql使用命令访问数据库_mysql命令操作数据库

    命令行创建数据库 CREATE DATABASE rst_xxh DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; 显示所有库 show data ...

  9. mysql日期减7天_Mysql 时间操作(当天,昨天,7天,30天,半年,全年,季度)

    1 . 查看当天日期 select current_date(); 2. 查看当天时间 select current_time(); 3.查看当天时间日期 select current_timesta ...

最新文章

  1. 【AJAX】Ajax学习总结
  2. get请求乱码问题,用encodeURI和decodeURI
  3. Linux 在 linux 中搭建 FTP 服务
  4. MATLAB使用Python数值和字符变量
  5. 如何黑掉一台根本不联网的电脑
  6. k8s kubectl run命令使用详解
  7. Flask实战第41天:发送短信验证码
  8. 全能终端神器 --- MobaXterm 、开启 linux 远程桌面
  9. 编程之美-3.5-最短摘要的生成
  10. 常用函数(PHP/Java/MySQL)
  11. NeurIPS 2019:进入NLP的黄金时代
  12. QML 圆角进度条实现 圆角剪切
  13. eclipse配置tomcat日志保存位置
  14. 量子计算机原理 纠缠,白话量子计算机原理【前面的那个有错误,重新理清了一下思路】...
  15. 2021-4-22-Python自动化31期-day01作业答案
  16. 不要STUPID,坚持GRASP和SOLID
  17. 系统集成十大项目管理(1)
  18. 高等数学(第七版)同济大学 习题11-2 个人解答
  19. 微信小程序波浪动态效果和背景色渐变(使用动态图,有手就行,但是流动速度固定波浪数目也固定)
  20. 【花雕动手做】有趣好玩的音乐可视化系列小项目(14)---水杯水瓶灯

热门文章

  1. 全面预算管理体系的框架与落地
  2. siki学院_Unity初级案例_愤怒的小鸟_学习笔记2/3
  3. 智能床垫会成养老主流方式
  4. [整理]统计数据的可视化——图表绘制(一)
  5. 了解浏览器cookie以及浏览器缓存
  6. 万哥 给我发几个图片 私聊
  7. 最新《煤矿井下人员定位系统安全标志管理方案(试行)》等通知,助力煤矿新进程
  8. 分箱(binning)
  9. 如何用进度猫思维导图做项目管理?
  10. 让程序员血液沸腾的10个瞬间!