0
点赞
收藏
分享

微信扫一扫

【MySQL精通之路】InnoDB(9)-表和页压缩(1)-表压缩

目录

1.表压缩概述

2.创建压缩表

2.1 在FPT表空间中创建压缩表

2.2 在通用表空间中创建压缩表

2.3 压缩表的限制

3.优化InnoDB表的压缩

4.运行时监控InnoDB表压缩

5.InnoDB表的压缩工作原理

5.1 压缩算法

5.2 InnoDB数据存储和压缩

5.3 B树页面的压缩

5.4 压缩BLOB、VARCHAR和TEXT列

6.OLTP工作负载的压缩

7.SQL压缩语法警告和错误

7.1 file-per-table表空间的SQL压缩语法警告和错误

7.2 通用空间的SQL压缩语法警告和错误



1.表压缩概述

        由于处理器和高速缓冲存储器的速度比磁盘存储设备更快,因此许多工作负载都是磁盘有关的。数据压缩能够以提高CPU利用率的小成本实现更小的数据库大小减少I/O提高吞吐量

        压缩对于读密集型应用程序尤其有价值,因为在具有足够RAM以将频繁使用的数据保存在内存中的系统上。

        使用ROW_FORMAT=COMPRESED创建的InnoDB表可以在磁盘上使用比配置的innodb_page_size值更小的页面大小。

        较小的页面需要较少的I/O读取写入磁盘,这对SSD设备尤其有价值。

        压缩页面大小是通过CREATE TABLEALTER TABLE KEY_BLOCK_SIZE参数指定的。不同的页面大小要求将表放在FPT表空间通用表空间文件中,而不是放在系统表空间中,因为系统表空间无法存储压缩的表

        无论KEY_BLOCK_SIZE值如何,压缩级别都是相同的。

        当您为KEY_BLOCK_SIZE指定更小的值时,您可以获得越来越小的页面带来的I/O好处。

        但是,如果指定的值太小,当数据值无法压缩到足以容纳每页中的多行时,则会有额外的开销来重新组织页面。根据表中每个索引的键列长度,KEY_BLOCK_SIZE的大小有一个严格的限制。指定的值太小,CREATE TABLE或ALTER TABLE语句将失败。

        在缓冲池中,压缩数据保存在小页面中,页面大小基于KEY_BLOCK_SIZE值。为了查询或更新列值,MySQL还使用未压缩的数据在缓冲池中创建一个未压缩的页面。在缓冲池中,对未压缩页面的任何更新也会被重新写回等效的压缩页面。您可能需要调整缓冲池的大小以容纳压缩页未压缩页额外数据,尽管在需要空间时会将未压缩页从缓冲池中移出,然后在下次访问时再次进行压缩。


2.创建压缩表

压缩表可以在FPT表空间通用表空间中创建。表压缩不适用于InnoDB系统表空间

系统表空间(space0,.ibdata文件)可以包含用户创建的表,但也包含从不压缩的内部系统数据。因此,压缩仅适用于FPT表空间通用表空间中的表(和索引)。

2.1 在FPT表空间中创建压缩表

要在FPT表空间中创建压缩表,必须启用innodb_file_per_table(默认设置)。

您可以在MySQL配置文件(my.cnf或my.ini)中设置此参数,也可以使用set语句动态设置此参数。

配置innodb_file_per_table选项后,在CREATE TABLE或ALTER TABLE语句中指定ROW_FORMAT=COMRESSED子句KEY_BLOCK_SIZE子句,或同时指定这两个子句,以在FPT表空间中创建压缩表。

例如,您可以使用以下语句:

SET GLOBAL innodb_file_per_table=1;
CREATE TABLE t1
 (c1 INT PRIMARY KEY)
 ROW_FORMAT=COMPRESSED
 KEY_BLOCK_SIZE=8;

2.2 在通用表空间中创建压缩表

        要在通用表空间中创建压缩表,必须为创建表空间时指定的通用表空间定义FILE_BLOCK_SIZE

FILE_BLOCK_SIZE值必须是相对于innodb_page_size值的有效压缩页大小,并且由CREATE TABLEALTER TABLE KEY_BLOCK_IZE子句定义的压缩表的页大小必须等于FILE_BLOCC_SIZE/1024

例如,如果innodb_page_size=16384FILE_BLOCK_SIZE=8192,则表的KEY_BLOCK_IZE必须为8。

以下示例演示了创建一个通用表空间和添加一个压缩表

该示例假设默认的innodb_page_size16K8192FILE_BLOCK_SIZE要求压缩表的KEY_BLOCK_IZE为8

mysql> CREATE TABLESPACE `ts2` ADD DATAFILE 'ts2.ibd' FILE_BLOCK_SIZE = 8192 Engine=InnoDB;

mysql> CREATE TABLE t4 (c1 INT PRIMARY KEY) TABLESPACE ts2 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;


注意: 

2.3 压缩表的限制

3.优化InnoDB表的压缩

待补充


4.运行时监控InnoDB表压缩

        应用程序的总体性能CPUI/O利用率及磁盘文件的大小都很好地指示了压缩对应用程序的有效性。本节基于“InnoDB表的调优压缩”中的性能调优建议,并展示了如何查找初始测试过程中可能不会出现的问题。

        为了深入了解压缩表的性能注意事项,可以使用示例“使用压缩Information Schema表”中描述的Information Schema表在运行时监视压缩性能。这些表反映了内存的内部使用情况总体使用的压缩率

        INNODB_CMP表报告有关正在使用的每个压缩页面大小(KEY_BLOCK_SIZE)的压缩活动的信息。这些表中的信息是全系统的:它总结了数据库中所有压缩表压缩统计信息。当没有其他压缩表被访问时,您可以通过检查这些表来使用这些数据来帮助决定是否压缩表。它在服务器上的开销相对较低,因此您可以在生产服务器定期查询它,以检查压缩功能的总体效率

        INNODB_CMP_PER_INDEX表报告有关各个表索引压缩活动的信息。这些信息更有针对性,对于评估压缩效率和诊断性能问题更有用,每次一个表索引。(因为每个InnoDB表都表示为聚集索引,MySQL在这种情况下不会对索引进行太大区分。)InnoDB_CMP_PER_INDEX表确实涉及大量开销,因此它更适合开发服务器,在那里可以单独比较不同工作负载、数据和压缩设置的效果。为了防止意外施加这种监视开销,必须先启用innodb_cp_per_index_enabled配置选项,然后才能查询innodb_cmp_per_index表

        要考虑的关键统计数据是执行压缩解压缩操作的次数以及所花费的时间。由于MySQL在B树节点太满无法包含修改后的压缩数据会对其进行拆分,因此请将“成功”压缩操作的数量与此类操作的总体数量进行比较。根据INNODB_CMPINNODB_CMP_PER_INDEX表中的信息以及整体应用程序性能硬件资源利用率,您可以更改硬件配置、调整缓冲池的大小、选择不同的页面大小或选择不同的表集进行压缩。

        如果压缩解压缩所需的CPU时间很长,那么在相同的数据、应用程序工作负载和一组压缩表的情况下,改用更快多核CPU可以帮助提高性能增加缓冲池的大小也可能有助于提高性能,使更多未压缩的页面可以留在内存中,从而减少仅以压缩形式存在于内存中的页面进行解压缩的需要。

        总体而言,大量的压缩操作(与应用程序中的INSERT、UPDATE和DELETE操作的数量以及数据库的大小相比)可能表明某些压缩表的更新过多无法进行有效的压缩。如果是这样,请选择更大的页面大小,或者对压缩的表更有选择性。

        如果“成功”压缩操作(COMPRESS_OPS_OK)的数量占压缩操作总数(COMPREST_OPS)的百分比很高,则系统可能运行良好。如果比率较低,那么MySQL重组重新压缩拆分B树节点频率高于预期。在这种情况下,请避免压缩某些表,或增加某些压缩表的KEY_BLOCK_SIZE。对于导致应用程序中“压缩失败”的数量超过总数的1%或2%的表,您可能会关闭压缩。(在诸如数据加载之类的临时操作期间,这样的故障率可能是可接受的)。

5.InnoDB表的压缩工作原理

本节描述了一些关于InnoDB表压缩的内部实现细节。这里提供的信息可能有助于调整性能,但对于压缩的基本用途来说,这不是必须的。

5.1 压缩算法

        一些操作系统在文件系统级别实现压缩。

        文件通常被划分固定大小的块,这些块被压缩为可变大小的块。这很容易导致碎片化。每次修改块中的某个内容时,都会在将整个块写入磁盘之前对其进行重新压缩。这些特性使得这种压缩技术不适合在更新密集型数据库系统中使用

        MySQL借助著名的zlib库实现压缩,该库实现了LZ77压缩算法

        这种压缩算法在CPU利用率减少数据大小方面都是成熟稳健高效的。

        该算法是“无损”的,因此原始的未压缩数据总是可以从压缩的形式中重建。

        LZ77压缩的工作原理是找到要压缩的数据中重复的数据序列。数据中的值模式决定了它的压缩效果,但典型的用户数据通常压缩50%或更多。

        与应用程序执行的压缩或其他一些数据库管理系统的压缩功能不同,InnoDB压缩既适用于用户数据,也适用于索引。在许多情况下,索引可能占数据库总大小的40-50%或更多,因此这种差异是显著的。

        当数据集的压缩工作正常时,InnoDB数据文件的大小(每个表空间或通用表空间.ibd文件的文件)是未压缩大小的25%到50%,或者可能更小。根据工作负载的不同,这个较小的数据库反过来可以减少I/O提高吞吐量,而在提高CPU利用率方面的成本并不高。

5.2 InnoDB数据存储和压缩

InnoDB表中的所有用户数据都存储在包含B树索引(聚集索引)的中。

在其他一些数据库系统中,这种类型的索引被称为“索引组织表”。索引节点中的每一行都包含(用户指定或系统生成的)主键表中所有其他列的值

InnoDB表中的二级索引也是B树,包含成对的值:索引键指向聚集索引中一行的指针

指针实际上是表主键的值,如果需要索引键和主键以外的列,则用于访问聚集索引。辅助索引记录必须始终匹配单个B树页。

B树节点(包括聚集索引二级索引)的压缩用于存储长VARCHARBLOBTEXT列的溢出页的压缩处理方式不同,如下节所述。

5.3 B树页面的压缩

由于B树页面经常更新,因此需要进行特殊处理。重要的是要尽量减少B树节点的拆分次数

并尽量减少解压缩重新压缩其内容的需要。

        MySQL使用的一种技术是以未压缩的形式维护B树节点中的一些系统信息,从而促进某些即时更新。例如,这允许在不进行任何压缩操作的情况下对行进行标记删除(标记为删除但未删除)和删除。

        此外,MySQL试图避免在索引页更改时对其进行不必要的解压缩和重新压缩

        当修改日志的空间用完时,InnoDB会解压缩页面应用更改并重新压缩页面。如果重新压缩失败(这种情况被称为压缩失败),B树节点将被拆分,并重复该过程,直到更新或插入成功。

        为了避免在写密集型工作负载(如OLTP应用程序)中频繁出现压缩故障,MySQL有时会在页面中保留一些空白空间(填充),以便修改日志更快地填满,并在仍有足够空间避免拆分的情况下重新压缩页面。随着系统跟踪页面拆分的频率,每个页面中剩余的填充空间量会有所不同。在频繁写入压缩表的繁忙服务器上,可以调整innodb_compression_failure_threshold_pctinnodb_impression_pad_pct_max配置选项来微调此机制


        通常,MySQL要求InnoDB表中的每个B树页面至少可以容纳两条记录。对于压缩表,这一要求已经放宽

        B树节点的叶页(无论是主键还是辅助索引)只需要容纳一条记录,但该记录必须以未压缩的形式放入每页修改日志中。

        如果innodb_strict_mode为ON,MySQL将在CREATE TABLE或CREATE INDEX期间检查最大行大小。如果行不适合,则会发出以下错误消息:ERROR HY000: Too big row.


        如果在innodb_strict_mode为OFF时创建表,并且随后的INSERT或UPDATE语句试图创建

不适合压缩页大小的索引项,则操作将失败,并返回错误42000:Row size too large.

(此错误消息没有命名记录过大的索引,也没有提及索引记录的长度或该特定索引页上的最大记录大小。)

        innodb_strict_mode不适用于同样支持压缩表的通用表空间一般表空间的表空间管理规则是独立于innodb_strict_mode严格执行的。

5.4 压缩BLOB、VARCHAR和TEXT列

        在InnoDB表中,不属于主键的BLOB、VARCHARTEXT列可以存储在单独分配的溢出页上。我们将这些列称为页外列。它们的值存储在溢出页单链接列表中。

        对于在ROW_FORMAT=DYNAMICROW_FORMAT=COMPRESED中创建的表,BLOB、TEXT或VARCHAR列的值可以完全页外存储,这取决于它们的长度整行的长度

        对于页外存储的列,聚集索引记录只包含指向溢出页的20字节指针,每列一个。

        是否有任何列存储在页外取决于页大小行的总大小。当该行太长而无法完全容纳在聚集索引的页面中时,MySQL会选择最长的列作为页外存储,直到该行适合聚集索引页面。如上所述,如果一行本身不适合压缩页面,则会发生错误。

        使用ROW_FORMAT=REDUNDANTROW_FORMT=COMPACT的表将BLOB、VARCHAR和TEXT列前768个字节主键一起存储在聚集索引记录中。

768字节的前缀后面跟着一个20字节的指针,指向包含列值其余部分的溢出页

        当表为COMPRESSED格式时,所有写入溢出页的数据都会“按原样”压缩;也就是说,MySQL将zlib压缩算法应用于整个数据项

        除了数据之外,压缩的溢出页还包含未压缩的报头尾部,该报头尾部包括页校验和到下一个溢出页的指针等。因此,如果数据是高度可压缩的,那么对于较长的BLOB、TEXT或VARCHAR列,可以获得非常显著的存储节省,文本数据通常就是这样。

        图像数据,例如JPEG,通常已经被压缩,因此存储在压缩表中没有太大好处;双重压缩会浪费CPU周期,而且节省很少的空间或根本不节省空间。

        溢出页面的大小与其他页面相同。即使列的总长度只有8K字节,一个包含十列的行也会占用十个溢出页。在未压缩的表中,10个未压缩的溢出页占用160K字节在8K页面大小的压缩表中,它们只占用80K字节。因此,对于具有长列值的表,使用压缩表格式通常更有效。

        对于每个表的文件表空间,使用16K压缩的页面大小可以降低BLOB、VARCHAR或TEXT列的存储和I/O成本,因为这些数据通常压缩得很好,因此可能需要更少的溢出页面,即使B树节点本身占用的页面与未压缩形式的页面一样多。一般表空间不支持16K压缩页面大小(KEY_BLOCK_SIZE)。

6.OLTP工作负载的压缩

        传统上,InnoDB压缩功能主要推荐用于只读以读取为主的工作负载,例如在数据仓库配置中。

        SSD存储设备速度快但相对较小且价格昂贵,这使得压缩对OLTP工作负载也很有吸引力:高流量交互式网站可以通过将压缩表频繁执行INSERTUPDATEDELETE操作的应用程序一起使用,来降低其存储要求每秒I/O操作(IOPS)。

        通过这些配置选项,您可以调整特定MySQL实例的压缩工作方式,重点关注写密集型操作的性能和可扩展性:

因为处理压缩数据有时需要同时将页面的压缩版本和未压缩版本保存在内存中,所以在OLTP风格的工作负载中使用压缩时,请准备增加innodb_buffer_pool_size配置选项的值。


7.SQL压缩语法警告和错误

本节介绍将表压缩功能用于file-per-table表空间通用表空间时可能遇到的语法警告错误

7.1 file-per-table表空间的SQL压缩语法警告和错误

7.2 通用空间的SQL压缩语法警告和错误

如果在创建表空间时没有为通用表空间定义FILE_BLOCK_SIZE,则表空间不能包含压缩表。如果尝试添加压缩表,则会返回一个错误,如以下示例所示:

mysql> CREATE TABLESPACE `ts1` ADD DATAFILE 'ts1.ibd' Engine=InnoDB;

mysql> CREATE TABLE t1 (c1 INT PRIMARY KEY) TABLESPACE ts1 ROW_FORMAT=COMPRESSED
       KEY_BLOCK_SIZE=8;
ERROR 1478 (HY000): InnoDB: Tablespace `ts1` cannot contain a COMPRESSED table

 尝试将KEY_BLOCK_SIZE无效的表添加到通用表空间会返回错误,如以下示例所示:

mysql> CREATE TABLESPACE `ts2` ADD DATAFILE 'ts2.ibd' FILE_BLOCK_SIZE = 8192 Engine=InnoDB;

mysql> CREATE TABLE t2 (c1 INT PRIMARY KEY) TABLESPACE ts2 ROW_FORMAT=COMPRESSED
       KEY_BLOCK_SIZE=4;
ERROR 1478 (HY000): InnoDB: Tablespace `ts2` uses block size 8192 and cannot
contain a table with physical page size 4096

对于通用表空间,表的KEY_BLOCK_SIZE必须等于表空间的FILE_BLOCK_IZE除以1024。例如,如果表空间的FILE_BLOCK_SIZE为8192,则表的KEY_BLOCK_IZE必须为8。


 试图将未压缩行格式的表添加到配置为存储压缩表的通用表空间中会返回错误,如以下示例所示:

mysql> CREATE TABLESPACE `ts3` ADD DATAFILE 'ts3.ibd' FILE_BLOCK_SIZE = 8192 Engine=InnoDB;

mysql> CREATE TABLE t3 (c1 INT PRIMARY KEY) TABLESPACE ts3 ROW_FORMAT=COMPACT;
ERROR 1478 (HY000): InnoDB: Tablespace `ts3` uses block size 8192 and cannot
contain a table with physical page size 16384

innodb_strict_mode不适用于通用表空间通用表空间的表空间管理规则是独立于innodb_strict_mode严格执行的。

下一篇:

【MySQL精通之路】InnoDB(9)-表和页压缩(2)-页压缩-CSDN博客

举报

相关推荐

0 条评论