加入收藏 | 设为首页 | 会员中心 | 我要投稿 湖南网 (https://www.hunanwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程 > 正文

MySQL删除操作其实是假删除

发布时间:2019-05-31 15:19:51 所属栏目:编程 来源:谭小谭啊
导读:在 InnoDB 中,你的 delete 操纵,并不会真的把数据删除,mysql 现实上只是给删除的数据打了个标志,标志为删除,因此你行使 delete 删除表中的数据,表文件在磁盘上所占空间不会变小,我们这里临时称之为假删除。 上面这个是结论,我们可以通过一个例子来
副问题[/!--empirenews.page--]

MySQL删除操纵着实是假删除

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

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

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

  1. CREATE TABLE `t` ( 
  2.   `id` int(11) NOT NULL, 
  3.   `a` int(11) DEFAULT NULL, 
  4.   `b` int(11) DEFAULT NULL, 
  5.   PRIMARY KEY (`id`), 
  6.   KEY `a` (`a`), 
  7.   KEY `b` (`b`) 
  8. ) ENGINE=InnoDB;  
  1. #界说支解标记,mysql 默认支解符为分号;,这里界说为 // 
  2. #脱离符的浸染首要是汇报mysql碰着下一个 // 标记即执行上面这一整段sql语句 
  3. delimiter // 
  4.  
  5. #建设一个存储进程,并定名为 testData 
  6. create procedure testData()  
  7.  
  8. #下面这段就是暗示轮回往内外插入10w条数据 
  9. begin 
  10.   declare i int; 
  11.   set i=1; 
  12.   while(i<=100000)do 
  13.     insert into t values(i, i, i); 
  14.     set i=i+1; 
  15.   end while; 
  16. end //  #这里碰着//标记,即执行上面一整段sql语句 
  17.  
  18. delimiter ; #规复mysql脱离符为; 
  19.  
  20. call testData(); #挪用存储进程  
  1. #下面这两条呼吁可以查察表文件所占空间巨细 
  2. mysql> use information_schema; 
  3. Reading table information for completion of table and column names 
  4. You can turn off this feature to get a quicker startup with -A 
  5.  
  6. Database changed 
  7. mysql> select concat(round(sum(DATA_LENGTH/1024/1024),2),'M') from tables where table_schema='test' AND table_name='t'; 
  8. +-------------------------------------------------+ 
  9. | concat(round(sum(DATA_LENGTH/1024/1024),2),'M') | 
  10. +-------------------------------------------------+ 
  11. | 3.52M                                           | 
  12. +-------------------------------------------------+ 
  13. 1 row in set (0.04 sec) 

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

  1. #先删除表全部数据,再从头查察表文件巨细 
  2. mysql> delete from t; 
  3. Query OK, 100000 rows affected (0.46 sec) 
  4.  
  5. mysql> use information_schema; 
  6. Reading table information for completion of table and column names 
  7. You can turn off this feature to get a quicker startup with -A 
  8.  
  9. Database changed 
  10. mysql> select concat(round(sum(DATA_LENGTH/1024/1024),2),'M') from tables where table_schema='test' AND table_name='t'; 
  11. +-------------------------------------------------+ 
  12. | concat(round(sum(DATA_LENGTH/1024/1024),2),'M') | 
  13. +-------------------------------------------------+ 
  14. | 3.52M                                           | 
  15. +-------------------------------------------------+ 
  16. 1 row in set (0.00 sec) 

从功效可以发明表数据被清空后,表所占空间巨细并没有变革,这就验证了上面的结论,delete 操纵并没有真正删除数据,表的空间并没有被开释。

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

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

尚有一种环境是数据页复用,就是指整个数据页都被标志删除了,于是这整个数据页都可以被复用了,和行记录复用差异的是,数据页复用对要插入的数据险些没有前提限定。

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

这些被标志删除的记录,着实就是一个朴陋,有种占着茅坑不拉屎的感受,挥霍空间不说,还会影响查询服从。

(编辑:湖南网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读