问题出现的情景:
店铺信息表中有几个店铺介绍相关存储富文本的字段,最初店铺数据量少时是用的Text字段,后来数据量增长导致DBA要求取消Text类型改为普通字符类型存储。
问题是如果直接把Text改成varchar类型的话,会直接报错导致类型变更失败。因为mysql5.0以上版本要求,单条数据所有普通类型(不含Text blob等类型)字段长度最大为65535字节,如果按照中文按三个字节算则最多存储65535/3个汉字。因为之前线上该text字段已经存储了信息,所有text字段数据加起来已经有超过了两万字,所以没有办法直接把text转成varchar类型。
故产生此问题。
因为该text字段存储的是富文本信息,故其中有很多重复的经过转义的html标签,且在数据库中该字段不会进行where查询,所以产生了 一种解决方案:把字段压缩后再存储来满足数据库对于长度的限制。
过程如下
- 把这个t_shop表备份到备份表 t_shop2
- 然后清空t_shop2表的text字段数据
- t_shop2的text类型改为varbinary类型
- 把清空的数据从t_shop 中读出压缩并写入t_shop2中
- 成功后t_shop更名为t_shop_dump, t_shop2更名为t_shop
- 上线项目,项目中sql对于富文本字段读取时增加uncompress,存储是进行compress
经测试原来长度20000的富文本压缩后只有1.7k,即不到两千字节,可以较为轻松的解决这个技术需求。
这么处理有三个优点:
- 因为进行了压缩,可以在65535的限制内存入数据,而富文本的内容特性也使得对它进行压缩会产生很大的收益效果。
- 而为什么要用varbinary来保存压缩后的字段,因为压缩后数据是byte字节数组,不能使用varchar类型存储。
- 原始数据没有变动存在了备份表中,以防上线出现问题及时回退。
需要注意的就是对于varbinary存储的压缩的中文数据,解压缩后需要强制转换成char不然可能会乱码,cast(uncompress(shop_info) as char)。