MySQL表压缩和页压缩,难道只是空间压缩?

临近春节,相信每个公司都会进行全面巡检,无论是业务层还是数据库层,达到事前预防的目的;今天就来分享一下针对mysql数据存储层面,在数据库存储来不及扩容的情况下,mysql中的压缩方案;

日常工作中很多业务在表结构设计之初不会考虑存储的设计,只有当业务发展到一定规模才会意识到问题的严重性。而物理存储主要是考虑是否要启用表的压缩功能,默认情况下,所有表都是非压缩的。但说到压缩,总会下意识地认为压缩会导致 MySQL 数据库的性能下降。这个观点说对也不对,需要根据不同场景进行区分。

目前很多引擎表支持压缩,比如 Myisam、InnoDB、TokuDB、MyRocks 。本文主要是针对Innodb引擎表压缩进行说明,针对MyRocks引擎的详细可参考:《RocksDB引擎和Innodb性能对比》。

数据库存储磁盘如果是非SSD的,数据库几乎都是 IO 负载型的,在 CPU 有大量余量的时候,磁盘 IO 的瓶颈就已经凸显出来。而数据的大量存储,尤其是日志型数据,会导致磁盘空间快速增长。硬盘不够用也会在很多业务中凸显出来。一种比较好的方式就诞生了,那就是通过牺牲少量 CPU 资源,采用压缩来减少磁盘空间占用,以及优化 IO 和带宽。尤其针对读多写少的业务。

如果存储磁盘是SSD,数据库的 IO 负载有所降低,但是对于磁盘空间的问题还是没有很好的解决。因此压缩表使用还是非常的广泛。这也就是为什么那么多的引擎都支持压缩的原因。而 innodb 在 MySQL 5.5 的时候就支持了压缩功能,只是压缩比比较低,通常在 50%左右。而 TokuDB 能达到 80%左右,MyRocks 的压缩比能达到 70%左右。

注意:压缩比和你存储的数据组成有很大的关系,并不是所有的数据都能达到上面所说的压缩比。如果大部分都是字符串,并且重复的数据比较多,压缩比会很好。

表压缩

数据库中的表是由一行行记录(rows)所组成,每行记录被存储在一个页中,在 MySQL 中,一个页的大小默认为 16K,一个个页又组成了每张表的表空间。通常我们认为,如果一个页中存放的记录数越多,数据库的性能越高。这是因为数据库表空间中的页是存放在磁盘上,MySQL 数据库先要将磁盘中的页读取到内存缓冲池,然后以页为单位来读取和管理记录。

一个页中存放的记录越多,内存中能存放的记录数也就越多,那么存取效率也就越高。若想将一个页中存放的记录数变多,可以启用压缩功能。此外,启用压缩后,存储空间占用也变小了,同样单位的存储能存放的数据也变多了。

如果要使用 innodb 压缩前提条件是:innodb_file_per_table 这个参数要启用,innodb_file_format 这个参数设置成 Barracuda。

COMPRESS 页压缩是 MySQL 5.7 版本之前提供的页压缩功能。只要在创建表时指定ROW_FORMAT=COMPRESS,并设置通过选项 KEY_BLOCK_SIZE 设置压缩的比例;如果没有指定 KEY_BLOCK_SIZE 的大小,默认 KEY_BLOCK_SIZE 为 innodb_page_size 大小的一半,也可以通过指定 KEY_BLOCK_SIZE=n 参数来开启 innodb 的压缩功能,n 可以为 1、2、4、8、16,单位是 K。n 的值越小,压缩比越高,消耗的 CPU 资源也越多。

注意:32K 或者 64K 的页不支持压缩。启用压缩后,索引数据也同样会被压缩。

也可以通过调整 innodb_compression_level 来设置压缩的级别,级别从 1~9,默认是 6。级别越低,意味着压缩比越高,同时也意味着需要更多的 CPU 资源。

启用表的页压缩功能后,性能有明显损失,因为压缩需要有额外的开销。主要原因是一个压缩页在内存缓冲池中,存在压缩和解压两个页。在 buffer_pool 缓冲池中,压缩的数据通过 KEY_BLOCK_SIZE 的大小的页来保存,如果要提取压缩的数据或者要更新压缩数据对应的列,则会创建一个未压缩页来解压缩数据,然后在数据更新完成后,会将为压缩页的数据重新写入到压缩页中。内存不足的时候,MySQL 会将对应的未压缩页踢出去。因此如果你启用了压缩功能,你的 buffer_pool 缓冲池中可能会存在压缩页和未压缩页,也可能只存在压缩页。不过可能仍然需要将你的 buffer_pool 缓冲池调大,以便能同时能保存压缩页和未压缩页。

如下是官方文档描述:

总之,COMPRESS 页压缩,适合用于一些对性能不敏感的业务表,例如日志表等

为了 解决压缩性能下降的问题,从MySQL 5.7 版本开始推出了 TPC 压缩功能,其利用文件系统的空洞(Punch Hole)特性进行压缩。

小门道AI 小门道AI

小门道AI是一个提供AI服务的网站

小门道AI 117 查看详情 小门道AI TPC 压缩( Innodb Transaparent PageIO Compression)

可以使用下面的命令创建 TPC 压缩表:

代码语言:javascript代码运行次数:0运行复制

CREATE TABLE Transaction (id BINARY(16) PRIMARY KEY,.....)COMPRESSION=ZLIB | LZ4 | NONE;

要使用 TPC 压缩,首先要确认当前的操作系统是否支持空洞特性。通常来说,当前常见的 操作系统都已支持空洞特性:

MySQL表压缩和页压缩,难道只是空间压缩?

在Linux系统上,文件系统块大小是空洞特性的单位大小。因此,只有当页面数据可以压缩到小于或等于InnoDB页面大小减去文件系统块大小时,页面压缩才起作用。例如,如果innodb_page_size=16K,文件系统块大小为4K,则页面数据必须压缩到小于或等于12K,才能生效。

这是因为不同于 COMPRESS 页压缩,TPC 压缩在内存中只有一个 16K 的解压缩后的页,对于缓冲池没有额外的存储开销。

表压缩在业务上的使用

总的来说,对一些对性能不敏感的业务表,例如日志表、账单表等,它们只对存储空间有要求,因此可以使用 COMPRESS 页压缩功能。

在一些较为核心的流水业务表上,更推荐使用 TPC压缩。因为流水信息是一种非常核心的数据存储业务,通常伴随核心业务。如一笔交易,下单、记流水,这就是一个核心业务的模型。

所以,用户对流水表有性能需求。此外,流水又非常大,启用压缩功能可更为有效地存储数据。

若对压缩产生的性能抖动有所担心,我的建议:由于流水表通常是按月或天进行存储,对当前正在使用的流水表不要启用 TPC 功能,对已经成为历史的周期表启用 TPC 压缩功能,如下所示:

MySQL表压缩和页压缩,难道只是空间压缩?

需要特别注意的是:通过命令 ALTER TABLE xxx COMPRESSION = ZLIB 可以启用 TPC 页压缩功能,但是这只对后续新增的数据会进行压缩,对于原有的数据则不进行压缩。所以上述ALTER TABLE 操作只是修改元数据,瞬间就能完成。

若想要对整个表进行压缩,需要执行 OPTIMIZE TABLE 命令:

代码语言:javascript代码运行次数:0运行复制

ALTER TABLE dic_history_202201 COMPRESSION=ZLIB;OPTIMIZE TABLE dic_history_202201;

禁用页面压缩

使用ALTER TABLE将compression设置为None。设置COMPRESSION=None后发生的表空间写入不再使用页压缩。要解压缩现有页面,必须在设置COMPRESSION=None后使用OPTIMIZE table重新生成表。

代码语言:javascript代码运行次数:0运行复制

ALTER TABLE dic_history_202201 COMPRESSION="None";OPTIMIZE TABLE dic_history_202201;

页压缩元数据

页压缩元数据存储在 INFORMATION_SCHEMA.INNODB_TABLESPACES表中,表中有三列:

代码语言:javascript代码运行次数:0运行复制

mysql>show create table employeesG*************************** 1. row ***************************Table: employeesCreate Table: CREATE TABLE `employees` (`emp_no` int NOT NULL,`birth_date` date NOT NULL,`first_name` varchar(14) NOT NULL,`last_name` varchar(16) NOT NULL,`gender` enum('M','F') NOT NULL,`hire_date` date NOT NULL,PRIMARY KEY (`emp_no`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMPRESSION='zlib'1 row in set (0.00 sec) mysql>SELECT SPACE, NAME, FS_BLOCK_SIZE, FILE_SIZE, ALLOCATED_SIZE FROM INFORMATION_SCHEMA.INNODB_TABLESPACES WHERE NAME='wjqtest/employees';+-------+-------------------+---------------+-----------+----------------+| SPACE | NAME | FS_BLOCK_SIZE | FILE_SIZE | ALLOCATED_SIZE |+-------+-------------------+---------------+-----------+----------------+| 265 | wjqtest/employees | 4096 | 114688 | 32768 |+-------+-------------------+---------------+-----------+----------------+1 row in set (0.00 sec) # ls -l /data/mysql_8306/data/wjqtest/employees.ibd-rw-r----- 1 mysql mysql 114688 Jan 11 11:22 /data/mysql_8306/data/wjqtest/employees.ibd # du --block-size=1 /data/mysql_8306/data/wjqtest/employees.ibd32768 /data/mysql_8306/data/wjqtest/employees.ibd

如上:在linux系统上,ls -l employees.ibd,以字节为单位显示明显的文件大小(相当于文件大小)。要查看磁盘上实际分配的空间量(相当于分配的大小),使用du –block-size=1 employees.ibd。–block size=1选项以字节而不是块的形式输入分配的空间,查询的结果和INFORMATION_SCHEMA.INNODB_TABLESPACES记录的结果一致。

页压缩限制和使用说明 小结

在进行表结构设计时,除了进行列的选择外,还需要考虑存储的设计,特别是对于表的压缩功能的设计,总结来说:

以上就是MySQL表压缩和页压缩,难道只是空间压缩?的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/463644.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年11月8日 04:35:27
下一篇 2025年11月8日 04:36:37

相关推荐

  • 怎样在C++中实现输入验证?

    在c++++中实现输入验证可以通过以下步骤实现:1) 使用循环和std::cin进行基本的输入检查;2) 封装验证逻辑到函数中,使用正则表达式进行复杂格式验证;3) 利用异常处理机制来处理验证错误。这些方法可以提高程序的健壮性和用户体验。 在C++中实现输入验证是编程中的一个关键技能,它不仅能提高程…

    2025年12月18日
    000
  • 如何在 sublime text 中运行 c++ 代码

    在 #%#$#%@%@%$#%$#%#%#$%@_348c++880664f2e1458b899ced2a3518e6 text 中运行 c++ 代码需要配置构建系统。1. 安装 c++ 编译器(如 mingw、xcode 或 gcc)。2. 创建并保存 c++.sublime-build 文件,定…

    2025年12月18日
    000
  • 制作计划的艺术

    C语言编程挑战与乐趣 学习编程语言并非易事,而我从未涉足C语言。尽管它看起来很有趣,但我决定写一篇博客记录我的学习历程。 您可能好奇我为什么选择C语言?说实话,我从未参与过大型项目开发,所以这将是一次充满挑战的经历,就像所有软件开发项目一样。后续我会持续更新进展。 C语言的魅力 C语言仍然拥有庞大的…

    2025年12月18日
    000
  • 堆栈框架和功能调用:如何创建CPU开销

    我痴迷于计算机科学与软件工程的方方面面,尤其对底层编程情有独钟。探索软件与硬件的交互机制,分析其边界行为,着实令人着迷。即使在高级应用编程中,这些知识也能帮助调试和解决问题,例如堆栈内存的运用。理解堆栈内存的工作原理,特别是与硬件交互时,对于避免和调试问题至关重要。 本文将探讨程序中频繁的函数调用如…

    2025年12月18日
    000
  • 分配C中的字符串

    让我们来分析一下这两段C语言代码,看看为什么它们的行为差异如此之大。 代码示例一: #include <stdio.h>int main(void){ char *string = "wello, world!"; string[0] = ‘h’; puts(stri…

    2025年12月18日
    000
  • libv是两个

    我开发了一个名为Lua-Libuv的项目,并乐于分享我的经验。项目初衷是探索如何利用Libuv(一个用C语言编写的异步I/O库)构建简单的HTTP服务器,而无需深入掌握C语言。 借助ChatGPT的辅助,我完成了HTTP.C的基础代码。在处理持久连接时,我成功实现了在适当的时机关闭连接并释放资源。起…

    好文分享 2025年12月18日
    000
  • 网络服务安装

    推介会: 本 SAE(业务学习情况)项目旨在开发一个基于客户端-服务器架构的实时“CAT”网络讨论应用程序。该应用允许多个客户端连接到中央服务器并进行实时通信。下图概述了套接字功能: 资源配置: 编程语言:C 语言版本控制:使用分布式 Github 进行代码共享开发环境:Visual Studio …

    2025年12月18日
    000
  • 嵌入式c语言和c语言区别 嵌入式c语言和c语言异同分析

    嵌入式C与标准C的区别在于:底层操作:嵌入式C直接操作硬件,而标准C主要通过操作系统接口交互。内存管理:嵌入式C注重节约内存,谨慎使用动态分配。库函数:嵌入式C包含必要的库函数,精简高效。可移植性:嵌入式C可移植性较差,需根据硬件平台修改代码。 嵌入式C与标准C:骨子里都流淌着C的血液,却有着不同的…

    2025年12月18日
    000
  • c语言与c十十的区别

    C 和 C++ 虽然同根同源,但因基因差异而走上不同道路:C:低级过程式语言,注重函数,需要手动内存管理,适合底层开发。C++:在 C 基础上增加了面向对象特性(如类、继承、多态),注重代码模块化和易维护性,但也增加了复杂度。 C 与 C++:兄弟俩,却走上了不同的路 你可能会问:C 和 C++ 有…

    2025年12月18日
    000
  • c语言和c哪个含金量好

    C 语言和 C++ 均为编程界的硬通货,其含金量取决于应用场景。C 语言擅长底层开发,如操作系统内核和嵌入式系统;C++ 则功能全面,适用于大型游戏开发和高性能计算。选择语言应基于职业规划和个人兴趣:操作系统或嵌入式系统选择 C 语言,游戏开发或高性能计算选择 C++。熟练掌握一门语言并运用到实践中…

    2025年12月18日
    000
  • C/C++ 中未使用的变量:为什么以及如何使用?

    在 C/C++ 代码审查中,经常会遇到未使用变量的情况。本文将探讨产生未使用变量的常见原因,并介绍如何让编译器发出警告以及如何抑制特定警告。 未使用变量的成因 代码中出现未使用变量的原因多种多样: 代码缺陷或错误: 最直接的原因是代码本身存在问题,变量可能根本不需要,或者需要但未被正确使用。代码重构…

    2025年12月18日
    000
  • 如何计算 CPU 百分比

    系统管理员经常面临一个棘手的问题:快速在机器上生成虚拟CPU负载。本文提供一种简单有效的解决方案,无需安装额外工具。 单核CPU负载: 最基础的方法是用C语言编写一个简单的无限循环程序。只需将以下代码保存为文件(例如,stressme.c),然后编译并运行: int main() {while (1…

    2025年12月18日
    000
  • C 编程中的指针 – 外行的类比

    c语言指针详解:告别困惑,轻松理解内存地址 指针是C语言中的一个核心概念,也是许多程序员感到困惑的点。本文将用通俗易懂的方式解释指针的含义,即使是初学者也能轻松理解。 房屋地址类比 我们将指针比作房屋地址。每栋房子都有一个独一无二的地址,而房子本身则代表存储的数据(变量)。 我们可以通过地址找到房子…

    2025年12月18日
    000
  • c++和c的语法区别 c和c++有什么区别

    C++和C的主要区别在于面向对象特性的加入,这使得C++更易于维护和扩展,但运行时开销也可能更高。C更精简高效,适合底层开发,但代码易于变得复杂。 C++和C:两种语言,两种世界 很多人问C++和C到底差在哪儿?简单说,C是C++的爸爸,但儿子已经远远超过了父亲。这可不是简单的继承关系,而是脱胎换骨…

    2025年12月18日
    000
  • c语言函数的执行顺序有哪些

    C语言函数的执行顺序并非从上到下那么简单,而是受到多种因素影响,包括函数调用方式、递归、指针以及异步操作。函数调用栈决定了函数执行顺序,而调用方式、递归、指针函数和函数指针以及异步操作复杂化了这个过程,带来了灵活性但同时也增加了难以预测性。 C语言函数执行顺序探秘:不止是自上而下那么简单 你是否曾经…

    2025年12月18日
    000
  • c语言函数怎么表示最大公约数教程

    C 语言中高效优雅地求最大公约数的方法:使用辗转相除法,通过不断除数取余直到余数为 0 的方式求解。提供了递归和迭代两种实现方式,递归实现简洁明了,迭代实现性能更高,更稳定。注意处理负数和 0 的情况,并考虑性能优化,但辗转相除法本身已足够高效。 C语言里怎么优雅地求最大公约数? 你可能觉得求最大公…

    2025年12月18日
    000
  • c语言函数的执行顺序是什么?有哪些?

    C语言函数的执行顺序取决于函数调用顺序和控制流语句。函数执行时,栈中堆叠的函数按后进先出顺序执行,即嵌套调用时先执行最内层函数。编译器、链接器等因素也可能影响函数最终执行顺序。 C语言函数的执行顺序?这问题问得妙啊,看似简单,实则暗藏玄机。很多初学者觉得,不就是从上到下依次执行吗? Naive!这可…

    2025年12月18日
    000
  • c语言函数库在什么位置?c语言函数库怎么添加?

    C语言函数库是一个包含各种函数的工具箱,这些函数被组织在不同的库文件中。添加函数库需要通过编译器的命令行选项来指定,例如 GCC 编译器使用 -l 选项,后跟库名的缩写。如果库文件不在默认搜索路径下,则需要使用 -L 选项指定库文件路径。库有静态库和动态库之分,静态库在编译时直接链接到程序中,而动态…

    2025年12月18日
    000
  • 【Rust自学】安装Rust

    1.1.1.从官方网站安装 rust 进入rust官网,右上角可以设置语言。 点击“开始”,您将看到以下界面: 根据您的操作系统选择合适的版本:32位系统选择32位,64位系统选择64位。现在大多数计算机都是 64 位的。如果您不确定,只要您的计算机不是很旧,下载 64 位版本就应该可以正常工作。 …

    2025年12月18日 好文分享
    000
  • c语言函数返回值是什么意思?由什么决定?

    C 语言函数返回值: 函数执行完成后返回给调用代码的数据,类型由函数定义确定。1. 返回类型决定于函数声明中的指定;2. 函数执行结果通过返回值途径送出;3. 返回类型与返回语句返回类型必须匹配;4. 忘记或错误设置返回值类型,或未使用返回语句都会导致错误;5. 返回值类型应清晰明确,提高代码可读性…

    2025年12月18日
    000

发表回复

登录后才能评论
关注微信