首页
技术小册
AIGC
面试刷题
技术文章
MAGENTO
云计算
视频课程
源码下载
PDF书籍
「涨薪秘籍」
登录
注册
01 | 基础架构:一条SQL查询语句是如何执行的?
02 | 日志系统:一条SQL更新语句是如何执行的?
03 | 事务隔离:为什么你改了我还看不见?
04 | 深入浅出索引(上)
05 | 深入浅出索引(下)
06 | 全局锁和表锁 :给表加个字段怎么有这么多阻碍?
07 | 行锁功过:怎么减少行锁对性能的影响?
08 | 事务到底是隔离的还是不隔离的?
09 | 普通索引和唯一索引,应该怎么选择?
10 | MySQL为什么有时候会选错索引?
11 | 怎么给字符串字段加索引?
12 | 为什么我的MySQL会“抖”一下?
13 | 为什么表数据删掉一半,表文件大小不变?
14 | count(*)这么慢,我该怎么办?
15 | 答疑文章(一):日志和索引相关问题
16 | “order by”是怎么工作的?
17 | 如何正确地显示随机消息?
18 | 为什么这些SQL语句逻辑相同,性能却差异巨大?
19 | 为什么我只查一行的语句,也执行这么慢?
20 | 幻读是什么,幻读有什么问题?
21 | 为什么我只改一行的语句,锁这么多?
22 | MySQL有哪些“饮鸩止渴”提高性能的方法?
23 | MySQL是怎么保证数据不丢的?
24 | MySQL是怎么保证主备一致的?
25 | MySQL是怎么保证高可用的?
26 | 备库为什么会延迟好几个小时?
27 | 主库出问题了,从库怎么办?
28 | 读写分离有哪些坑?
29 | 如何判断一个数据库是不是出问题了?
30 | 答疑文章(二):用动态的观点看加锁
31 | 误删数据后除了跑路,还能怎么办?
32 | 为什么还有kill不掉的语句?
33 | 我查这么多数据,会不会把数据库内存打爆?
34 | 到底可不可以使用join?
35 | join语句怎么优化?
36 | 为什么临时表可以重名?
37 | 什么时候会使用内部临时表?
38 | 都说InnoDB好,那还要不要使用Memory引擎?
39 | 自增主键为什么不是连续的?
40 | insert语句的锁为什么这么多?
41 | 怎么最快地复制一张表?
42 | grant之后要跟着flush privileges吗?
43 | 要不要使用分区表?
44 | 答疑文章(三):说一说这些好问题
45 | 自增id用完怎么办?
当前位置:
首页>>
技术小册>>
MySQL 实战 45 讲
小册名称:MySQL 实战 45 讲
### 13 | 为什么表数据删掉一半,表文件大小不变? 在MySQL数据库的日常管理和优化中,经常会遇到这样一个现象:即使删除了表中的大量数据(比如一半),表文件(.ibd或.MYD文件,取决于存储引擎)的大小却并未显著减少,这往往让数据库管理员感到困惑。要深入理解这一现象,我们需要从MySQL的存储引擎、数据页管理、以及InnoDB的表空间回收机制等多个方面进行探讨。 #### 一、MySQL存储引擎概述 MySQL支持多种存储引擎,每种引擎都有其特定的数据存储方式和管理机制。其中,InnoDB是最常用的存储引擎之一,它支持事务处理、行级锁定和外键等高级数据库功能。InnoDB使用表空间(Tablespace)来存储数据,表空间可以是一个或多个文件,这些文件包含了表的数据、索引以及MVCC(多版本并发控制)所需的信息。 #### 二、InnoDB的数据页与表空间 InnoDB将数据存储在称为“页”(Page)的固定大小(通常为16KB)的块中。每个页可以存储多行数据,具体取决于行的大小和页内其他元数据的占用情况。当表中的数据量增长时,InnoDB会动态地分配更多的页来存储新数据。然而,当数据被删除时,情况就变得复杂了。 #### 三、删除操作与空间释放 在InnoDB中,删除操作并不会立即从磁盘上移除数据页中的记录。相反,它会将记录标记为“已删除”(或称为“可重用”),这意味着这些空间现在可以被新的数据行所占用,但在物理层面上,数据页本身并未被删除或缩小。这种机制有助于减少磁盘I/O操作,因为频繁的磁盘读写操作会严重影响数据库性能。 #### 四、表空间回收的延迟性 由于InnoDB的这种设计,即使删除了大量数据,表空间的大小也不会立即减小。表空间的回收是一个相对缓慢且复杂的过程,它依赖于几个因素: 1. **自动合并与压缩**:InnoDB的后台进程会定期扫描表空间,尝试合并相邻的空闲页,以减少碎片并可能释放一些空间给文件系统。然而,这个过程是异步的,且效率受到多种因素的影响,如系统负载、I/O性能等。 2. **文件系统的限制**:即使InnoDB内部成功合并了空闲页,文件系统层面也可能因为文件系统的特性(如不支持文件大小动态减小)而无法反映这种变化。 3. **OPTIMIZE TABLE**:为了强制回收表空间,可以使用`OPTIMIZE TABLE`命令。这个命令会重建表,并在此过程中丢弃所有未使用的空间。然而,这个过程是资源密集型的,可能会暂时影响数据库性能,因此通常只在必要时使用。 4. **InnoDB的purge操作**:除了标记记录为“已删除”外,InnoDB还有一个专门的purge线程,负责清理这些已删除的记录。purge操作是异步进行的,且速度受到系统负载和配置参数的影响。只有当purge操作完成后,相应的空间才能真正被视为可重用的。 #### 五、如何有效管理表空间 面对表空间不随数据删除而减小的问题,数据库管理员可以采取以下策略来有效管理表空间: 1. **定期使用OPTIMIZE TABLE**:虽然这可能会带来性能开销,但在某些情况下(如表数据频繁变动且删除操作较多时),定期执行`OPTIMIZE TABLE`可以显著减少表空间的碎片,提高存储效率。 2. **合理设置InnoDB的配置参数**:通过调整如`innodb_file_per_table`(为每个表创建独立的表空间文件)、`innodb_purge_threads`(控制purge线程的数量)等参数,可以优化InnoDB的表空间管理和回收效率。 3. **监控和分析**:使用MySQL的性能监控工具(如`SHOW TABLE STATUS`、`INFORMATION_SCHEMA`中的表等)定期检查表的状态,包括数据长度、索引长度、碎片程度等,以便及时发现并处理表空间问题。 4. **考虑使用分区表**:对于非常大的表,可以考虑使用分区表来管理数据。分区表可以将一个大表分成多个较小的、更易于管理的部分,每个部分都可以独立地进行优化和维护。 5. **备份与恢复**:在极端情况下,如果表空间文件过大且难以通过常规手段减小,可以考虑通过导出数据、删除原表、重新创建表并导入数据的方式来“重置”表空间大小。但这种方法需要谨慎使用,因为它会中断数据库的正常运行。 #### 六、总结 MySQL中,尤其是使用InnoDB存储引擎时,表数据删除一半但表文件大小不变的现象是由InnoDB的存储机制和数据页管理方式决定的。理解这一现象背后的原理,有助于我们更好地管理MySQL的表空间,优化数据库性能。通过合理的配置、监控、以及必要的维护操作,我们可以确保数据库在高效运行的同时,也保持其存储空间的合理利用。
上一篇:
12 | 为什么我的MySQL会“抖”一下?
下一篇:
14 | count(*)这么慢,我该怎么办?
该分类下的相关小册推荐:
MySQL从入门到精通(三)
MySQL从入门到精通(一)
MySQL从入门到精通(四)
MySQL8.0入门与实践
MySQL从入门到精通(二)
MySQL必会核心问题
MySQL从入门到精通(五)
SQL零基础到熟练应用(增删改查)
细说MySQL(零基础到高级应用)