MySQL存储管理(一):删数据

news2024/10/7 10:20:03

从表中删除数据


从表中删除数据,也即是delete过程。

什么是表空间

表空间可以看做是InnoDB存储引擎逻辑结构的最高层,所有的数据都存放在表空间中。默认情况下,InnoDB存储引擎有一个共享表空间idbdata1,即所有数据都存放在这个表空间内。如果用户启用了参数 innodb_file_per_table,则每张表内的数据可以单独放到一个表空间内。

如果启用了 innodb_file_per_table 参数,需要注意的是每张表的表空间内存放的只是数据、索引和插入缓冲Bitmap页,其他类的数据,如回滚(undo)信息,插入缓冲索引页、系统事务信息,二次写缓冲(Double write buffer)等还是存放在原来的共享表空间内。这同时也说明了另一个问题,即使在启用了参数 innodb_file_per_table 之后,共享表空间还是会不断地增加其大小。

表数据存放

一个InnoDB表包含两部分, 即: 表结构定义和数据。

表结构定义

在MySQL 8.0版本以前, 表结构是存在以.frm为后缀的文件里。

从MySQL 8.0版本开始, 则已经允许把表结构定义放在系统数据表中了。 表结构定义占用的空间很小。

表数据

表数据既可以存在共享表空间里, 也可以是单独的文件。 这个行为是由参数innodb_file_per_table控制的:

  • 这个参数设置为OFF表示的是, 表的数据放在系统共享表空间, 也就是跟数据字典放在一起。
  • 这个参数设置为ON表示的是, 每个InnoDB表数据存储在一个以 .ibd为后缀的文件中。

从MySQL 5.6.6版本开始, 它的默认值就是ON了。

规范:建议你不论使用MySQL的哪个版本, 都将这个值设置为ON。 因为, 一个表单独存储为一个文件更容易管理, 而且在你不需要这个表的时候, 通过drop table命令, 系统就会直接删除这个文件。 而如果是放在共享表空间中, 即使表删掉了, 空间也是不会回收的。

清理表数据的方式有以下几种:

1)drop table:删除整个表,回收表空间;若表数据独立存放,则直接删除对应.ibd文件。

2)delete from table:只是把记录/数据页标记为“可复用”,但磁盘文件的大小是不会变。

3)truncate table:相当于drop+create。

数据删除流程

问1:使用delete删除表中的记录时,表空间没有被回收,为什么?

数据页存放在文件中,假设数据页中的一些记录被使用delete删除了,这时数据页并不会真正的删除这些记录,而是把这些记录标记为删除,即被标记删除的位置可以被复用。如果数据页上的所有记录都被删除了,则可以复用整个数据页。但是磁盘上,文件不会变小。

问2:记录的复用和数据页的复用有什么区别?

假设要删掉记录R4,InnoDB引擎只会把R4记录标记为删除。如果之后要再插入一个ID在300和600之间的记录时,可能会复用这个位置。但如果插入的是一个ID是800的行, 就不能复用这个位置了。

而当整个数据页中的记录都被删除时(整个页从B+树里面摘掉),可以复用到任何位置。 以下图为例, 如果将数据页page A上的所有记录删除以后, page A会被标记为可复用。 这时候如果要插入一条ID=50的记录需要使用新页的时候, page A是可以被复用的。

如果相邻的两个数据页利用率都很小, 系统就会把这两个页上的数据合到其中一个页上, 另外一个数据页就被标记为可复用。

执行delete命令后,这些可以复用,而没有被使用的空间,看起来就像是”空洞“。

实际上, 不止是删除数据会造成空洞, 插入数据、更新数据也会。

1)插入数据造成空洞

如果数据是按照索引递增顺序插入的, 那么索引是紧凑的。 但如果数据是随机插入的, 就可能造成索引的数据页分裂。假设下图中page A已经满了, 这时我要再插入一行数据, 会怎样呢?

可以看到, 由于page A满了, 再插入一个ID是550的数据时, 就不得不再申请一个新的页面page B来保存数据了。 页分裂完成后, page A的末尾就留下了空洞(注意: 实际上, 可能不止1个记录的位置是空洞) 。

2)更新数据造成空洞

更新索引上的值, 可以理解为删除一个旧的值, 再插入一个新值。 不难理解, 这也是会造成空洞的。

问:如何去掉这些空洞?

也就是说, 经过大量增删改的表, 都是可能存在空洞的。 所以, 如果能够把这些空洞去掉, 就能达到收缩表空间的目的。

而重建表,就可以达到这样的目的。

重建表

重建表的意义在于回收表空间,使得表的存储结构更加紧凑;

那么表又是如何重建的呢?

假设有一个表A,需要做空间收缩,把表中存在的空洞去掉,具体过程如下:

1)新建一个与表A结构相同的表B;

2)按照主键ID递增的顺序,把数据一行一行地从表A里读出来再插入到表B中;

3)把表B作为临时表, 数据从表A导入表B的操作完成后, 用表B替换A, 从效果上看, 就起到了收缩表A空间的作用。

MySQL可以使用如下命令重建表:

alter table A engine=InnoDB;

MySQL5.6之前版本重建表示意图:

显然, 花时间最多的步骤是往临时表插入数据的过程, 如果在这个过程中, 有新的数据要写入到表A的话, 就会造成数据丢失。 因此, 在整个DDL过程中, 表A中不能有更新。 也就是说, 这个DDL不是Online的。(MySQL5.6之前版本)

在MySQL 5.6版本开始引入的Online DDL, 对这个操作流程做了优化。引入了Online DDL之后, 重建表的流程:

1)建立一个临时文件,扫描表A主键的所有数据页;

2)用数据页中表A的记录生成B+树,存储到临时文件中;

3)生成临时文件的过程中,将所有对A的操作记录在一个日志文件(row log)中,对应的是图中state2的状态;

4)临时文件生成后,将日志文件中的操作应用到临时文件,得到一个逻辑数据上与表A相同的数据文件,对应的就是图中state3的状态;

5)用临时文件替换表A的数据文件;

MySQL5.6之后版本重建表示意图:

由于日志文件的存在,允许对表A做增删改操作。 这也就是Online DDL名字的来源,所谓Online,即对表进行DDL操作的同时,允许对该表进行增删改操作(DML)。

Online DDL过程需要加MDL锁(元数据锁),过程如下:

1)拿MDL写锁;

2)降级成MDL读锁;

3)真正做DDL;

4)升级成MDL写锁;

5)释放MDL锁;

之所以加写锁,是为了等待加读锁的DDL或DML完成;退化为读锁,是为了不阻塞DML语句的执行;

注1:

  • mysql
  • mysql >= 5.6,改进重建表过程,允许Online DDL。

注2:重建表的过程最耗时的是拷贝数据,因而该过程中允许DML,将会获得比较多的收益;这也是Online DDL的意义;

注3:对于大表进行重建表的操作消耗较大的CPU和IO,因而需要考虑在业务不繁忙的情况下进行;为保证安全,可以使用gh-ost工具;

Copy和Inplace

copy和inplace是重建表的两种策略,重建表默认使用的是inplace。

可以通过如下命令显示指定重建表的策略:

alter table t engine=innodb, ALGORITHM = inplace;
alter table t engine=innodb, ALGORITHM = copy;

问1:copy和inplace有什么区别?

1)copy的含义:当使用ALGORITHM=copy的时候, 表示的是强制拷贝表, 对应的流程就是上一小节第一张图的操作过程。

2)inlace的含义:在上一小节第二张图中,把表A重建出来的数据存放在“tmp_file”里的, 这个临时文件是InnoDB在内部创建出来的。 整个过程都是在InnoDB内部完成。对于server层来说, 没有把数据挪动到临时表, 是一个“原地”操作, 这就是“inplace”名称的来源。所谓inplace,是索引创建在原表上直接进行,而表数据依然需要数据拷贝;区别在于:

  • 拷贝过程不记录undo log和redo log;
  • 二级索引是有序的,可以按顺序加载;
  • 无需Change Buffer,因为对于二级索引没有随机写操作;

问2:如果你有一个1TB的表, 现在磁盘间是1.2TB, 能不能做一个inplace的DDL呢?

答:不能。

因为, tmp_file也是要占用临时空间的。我们重建表的这个语句alter table t engine=InnoDB, 其实隐含的意思是:

-- 重建表
alter table t engine=innodb, ALGORITHM=inplace;

问3:inplace跟Online是不是就是一个意思?

答:不是。只是在重建表这个逻辑中刚好是这样而已。

比如, 如果我要给InnoDB表的一个字段加全文索引, 写法是:

alter table t add FULLTEXT(field_name);

这个过程是inplace的, 但会阻塞增删改操作, 是非Online的。

如果说这两个逻辑之间的关系是什么的话, 可以概括为:

  • DDL过程如果是Online的, 就一定是inplace的;
  • 反过来未必, 也就是说inplace的DDL, 有可能不是Online的。 截止到MySQL 8.0, 添加全文索引(FULLTEXTindex) 和空间索引(SPATIAL index)就属于这种情况。

问4:使用optimize table、 analyze table和alter table这三种方式重建表有什么区别?

1)从MySQL 5.6版本开始, alter table t engine = InnoDB(也就是recreate) 默认的就是上一小节第二张图的流程了。

2)analyze table t 其实不是重建表, 只是对表的索引信息做重新统计, 没有修改数据, 这个过程中加了MDL读锁。

3)optimize table t 等于recreate+analyze。

问5:假设现在有人碰到了一个“想要收缩表空间,结果适得其反”的情况,看上去是这样的:

一个表t文件大小为1TB;

对这个表执行 alter table t engine=InnoDB;

发现执行完成后,空间不仅没变小,还稍微大了一点儿,比如变成了1.01TB。

你觉得可能是什么原因呢 ?

答:

1)这个表本身就已经没有空洞了,比如刚做过一次重建表操作。且在重建表的时候,InnoDB不会把整张表占满,每个页留了1/16给后续的更新用,所以重建之后,文件就反而变大了。

2)重建过程中,存在DML执行,因而在row log重新应用时,又产生了空洞。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1849520.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

力扣SQL50 各赛事的用户注册率 分组计数 双排序字段

Problem: 1633. 各赛事的用户注册率 👨‍🏫 参考题解 Code select contest_id, ROUND(COUNT(user_id) * 100 / (select count(*) from users),2) as percentage from register group by contest_id order by percentage desc, contest_id asc

Simulink添加自己的库,并给库添加子库

直接看官网教程,不要看残缺的大道法则 https://ww2.mathworks.cn/help/simulink/ug/adding-libraries-to-the-library-browser.html 文中涉及一个 属性检查器 在这里。

Day13-Spark SQL的学习

Spark SQL的学习 一.Spark SQL基础 二.Spark SQL整合hive 文章目录 Spark SQL的学习一、Spark SQL基础Spark SQL介绍DataFrame和DataSetSpark SQL的基本使用Spark SQL基本使用案例 Spark SQL函数内置函数自定义函数窗口(开窗)函数 二、Spark SQL整合Hiv…

ArcGIS arcpy代码工具——批量要素裁剪栅格影像

系列文章目录 ArcGIS arcpy代码工具——批量对MXD文件的页面布局设置修改 ArcGIS arcpy代码工具——数据驱动工具批量导出MXD文档并同步导出图片 ArcGIS arcpy代码工具——将要素属性表字段及要素截图插入word模板 ArcGIS arcpy代码工具——定制属性表字段输出表格 ArcGIS arc…

容器之笔记本构件演示

代码&#xff1a; #include <gtk-2.0/gtk/gtk.h> #include <glib-2.0/glib.h> #include <gtk-2.0/gdk/gdkkeysyms.h> #include <stdio.h>void rotate_book(GtkButton *button, GtkNotebook *notebook) {gtk_notebook_set_tab_pos(notebook, (notebook…

MySQL进阶——SQL优化

目录 1插入数据 1.1 insert 1.2大批量插入数据 2主键优化 3 order by 优化 4 group by 优化 5 limit 优化 6 count 优化 6.1概述 6.2 count用法 7 update优化 1插入数据 1.1 insert 优化方案主要有3种 批量插入数据 Insert into tb_test values(1,Tom),(2,Cat)…

详解 ClickHouse 的副本机制

一、简介 副本功能只支持 MergeTree Family 的表引擎&#xff0c;参考文档&#xff1a;https://clickhouse.tech/docs/en/engines/table-engines/mergetree-family/replication/ ClickHouse 副本的目的主要是保障数据的高可用性&#xff0c;即使一台 ClickHouse 节点宕机&#…

Web渗透-CSRF跨站请求伪造

跨站请求伪造&#xff08;Cross-Site Request Forgery&#xff0c;CSRF&#xff09;是一种网络攻击&#xff0c;通过利用受害者的身份认证状态在不知情的情况下执行恶意操作。通常&#xff0c;这种攻击会诱使用户点击恶意链接或访问一个特制的网站&#xff0c;从而触发不被用户…

python库BeeWare,一个如雷贯耳的可以创建原生应用程序的库

目录 BeeWare 包括以下主要组件和工具&#xff1a; 创建BeeWare虚拟环境 配置BeeWare 创建一个新的BeeWare项目&#xff08; Hello World! &#xff09; 尝试 Hello World 样例 BeeWare 是一个开源项目&#xff0c;旨在帮助开发者使用 Python 创建原生应用程序&#xff0c;…

后端路线指导(4):后端春招秋招经验分享

后端春招&秋招经验分享 春招(暑期实习) /秋招是应届生非常重要的应聘时间,每一个想就业的同学一定要有所了解! 本篇内容&#xff0c;老白将与大家分享暑期实习和秋招如何应对招聘的个人经验&#xff0c;希望每个同学看完都能有所收获! 首先说明一下老白对于面试核心竞争力的…

Android图片圆角转换 RoundedImageView开源项目 小记

属性的意义: makeramen:border_width“2dip” 表示图片的边框宽度为2个dp makeramen: corner_radius表示为 图片转圆角的弧度 修改 makeramen:corner_radius“100dip” 当 corner_radius 设置为100dp 的时候 会呈现为圆形 . ( 注: com.makeramen.rounded.Ro…

MySQL表的增删改查初阶(下篇)

本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人…

多重排序【今日题记】

多重排序 多重排序题目分析思路代码代码结构体知识多重排序 需要对多个条件进行排序,因此可以称之为多重排序。 题目 某生物实验室记录了n种(n<=1000)病毒信息,每种病毒都有编号、传染性和致病性三个基本信息,编号是1000-9999的人工编号,其中的传染性和致病性是用0-10…

SVN学习(002 svn冲突解决)

尚硅谷SVN高级教程(svn操作详解) 总时长 4:53:00 共72P 此文章包含第20p-第p29的内容 冲突 产生冲突的操作 &#xff08;第一种 相互不影响的操作&#xff09; 用户1修改第二行 用户2修改第四行 用户1提交 用户2提交&#xff0c;提交的时候会提示版本已过时 这时将用…

力扣SQL 即时食物配送 II min函数 嵌套查询

Problem: 1174. 即时食物配送 II &#x1f468;‍&#x1f3eb; 参考题解 Code -- 计算立即配送的订单百分比 select round (-- 计算订单日期与客户偏好配送日期相同的订单数量sum(case when order_date customer_pref_delivery_date then 1 else 0 end) * 100 /-- 计算总订…

掌握Three.js:学习路线,成为3D可视化开发的高手!

学习Three.js可以按照以下路线进行&#xff1a; 基础知识&#xff1a; 首先要了解基本的Web开发知识&#xff0c;包括HTML、CSS和JavaScript。如果对这些知识已经比较熟悉&#xff0c;可以直接进入下一步。 Three.js文档&#xff1a; 阅读Three.js官方文档是学习的第一步。官…

如何下载和安装SQLynx数据库管理工具? (MySQL作为测试数据库)

目录 1. 官网下载 2. 安装软件 3. 启动SQLynx软件 4. 开始使用 5. 执行第一条SQL语句 6. 总结 SQLynx是一款先进的Web SQL集成开发环境&#xff08;IDE&#xff09;&#xff0c;专为数据库管理、查询和数据分析设计。作为一个基于浏览器的工具&#xff08;同时也支持桌面…

掌握 NumPy:高效数组处理综合指南(第 1/2 部分)

掌握 NumPy&#xff1a;高效数组处理综合指南&#xff08;第 1/2 部分&#xff09; 文章目录 一、介绍二、什么是Numpy&#xff0c;我们为什么要使用它&#xff1f;三. 数组初始化四. 计算速度和内存使用量五、内存使用情况六、数据类型七、索引和切片 一、介绍 你们以前听说过…

连接和断开信号演示之二

代码; #include <gtk-2.0/gtk/gtk.h> #include <gtk-2.0/gdk/gdkkeysyms.h> #include <glib-2.0/glib.h> #include <stdio.h>void button_press(GtkEventBox *ebox,GdkEventButton *event,GtkLabel *label) {const char *citem;switch(event->type…