技术点来源于每周技术分享会,对于MySQL压缩的技术方案进行了分享,针对本次分享思考是否使用技术方案改造,并代入demo。
压缩相关的场景
翻阅大量资料才找到官网出处,附链接,我在《高性能MySQL》第三版中也并未找到此章节。
https://docs.gitcode.net/mysql/guide/the-innodb-storage-engine/innodb-compression-usage.html
对于表压缩甚至官方的文档也侧重于解释带来的好处,并没有压缩列常用,合理看下压缩表的限制就知道为什么了。
压缩表的限制
那么我们直接进入压缩列的部分。
MySQL的列压缩
MySQL 针对列的压缩目前直接的方案并不支持,但是在业务层面使用 MySQL 提供的压缩和解压函数来针对列进行压缩和解压操作。也就是要对某一列做压缩,就需要在写入的时候调用 COMPRESS 函数对那个列的内容进行压缩,然后存放到对应的列。读取的时候,使用 UNCOMPRESSED 函数对压缩的内容进行解压缩
适用场景:针对MySQL中某个列或者某几个列数据量特别大,一般都是varchar、text、char等数据类型(如果内容包含emoj表情则注意需要使用编码类型为utf8mb4)。
压缩算法
一些操作系统在文件系统级别实现压缩。文件通常被分成固定大小的块,这些块被压缩成可变大小的块,这很容易导致碎片。每次修改块内的某些内容时,都会在将整个块写入磁盘之前对其进行重新压缩。这些特性使得这种压缩技术不适合在更新密集型数据库系统中使用。
innodb 压缩借助的是著名的 zlib 库,采用 L777 压缩算法,这种算法在减少数据大小和 CPU 利用方面很成熟高效。同时这种算法是无损的,因此原生的未压缩的数据总是能够从压缩文件中重构,LZ777 实现原理是查找重复数据的序列号然后进行压缩,所以数据模式决定了压缩效率,一般而言,用户的数据能够被压缩 50%以上。
支持的字段类
压缩 BLOB、VARCHAR 和 TEXT 列
在 InnoDB 表中,BLOB、VARCHAR 和 TEXT不属于主键的列可以存储在单独分配的溢出页面.我们将这些列称为页外栏.它们的值存储在溢出页面的单链表中,压缩后的数据不能直接在SQL中查询显示,所以建议使用在记录列上。
mybaits-plus 处理方式类型处理器,用于 JavaType 与 JdbcType 之间的转换,用于 PreparedStatement 设置参数值和从 ResultSet或CallableStatement中取出一个值,mybaits-plus内置常用类型处理器通过TableField注解快速注入到 mybatis 容器中。
@Data
@Accessors(chain = true)
@TableName(autoResultMap = true)
public class User {
private Long id;
...
/**
* 注意!!必须开启映射注解
*
* @TableName(autoResultMap = true)
*
* 以下两种类型处理器,二选一 也可以同时存在
*
* 注意!!选择对应的 JSON 处理器也必须存在对应 JSON 解析依赖包
*/
@TableField(typeHandler = JacksonTypeHandler.class)
// @TableField(typeHandler = FastjsonTypeHandler.class)
private OtherInfo otherInfo;
}
那么针对本次的压缩类型来说则指定为TypeHandler来实现BaseTypeHandler(org.apache.ibatis.type.BaseTypeHandler)
实例SQL
select length(compress('你好👌')); -- 返回压缩后的字节数
select convert(uncompress(compress('hello 👌')) using 'utf8mb4')
insert into table xxx (对要压缩的字段使用compress())
对比压缩前后数据
SELECT UNCOMPRESSED_LENGTH(content) AS length, LENGTH(content) AS compress_length, UNCOMPRESS(content), content FROM `test_compress`
注意:当字段类型为longtext时不适用,表结构虽然为utf8mb4但仍旧报错
对于日常请求入参出参的记录表来说,如果长时间不使用该字段做任何业务逻辑,短暂问题也会通过ELK来查询问题,建议对参数字段进行压缩,能够大大减少内存使用,并通过调节设置参数减少使用CPU资源。
--- 我站在十字路口,如同站在时间长河的上游,转念回首,它仿佛踏着神辉在游走。