使用bytea的hex格式减小表占用的空间大小

2018-03-11  本文已影响0人  twistzhuo

背景

    随着数据量的不断增大,生产环境db集群的存储空间面临着比较大的压力,经过团队的讨论之后,决定把优化方向指向bytea的十六进制格式存储。生产环境中表的敏感字段会先通过sha256加密,这部分数据通过bytea的十六进制格式存储可以节省下不少的空间。

面临的问题

虽然看起来只是使用了postgres中的一种基本类型,但是在实施过程中却发现不是那么简单。在生产环境中,还需要考虑一个可靠性和稳定性的问题。下面做一个简单的回顾。

问题1:

    要使用bytea的hex格式存储数据,需要先使用字符串函数decode(target_column_value,'hex')进行解码,否则系统会做varchar到bytea类型的强制转换,达不到节省空间的目的。

    生产环境中存在大量的表是离线导入的(使用pgloader从文件中导入),这部分表按月更新。如果是仅仅修改varchar类型为bytea类型的话,在使用pgloader导入数据时,便会遇到上述的问题。

问题2:

    在现有架构中,业务方所有对db的访问都通过数据库访问中间件(导师的作品,名为ditto)来进行统一控制,而ditto的性能开销主要在cpu这一块,增加hex格式的编码和解码这一环节明显会增大ditto的压力。

方案

方案1    通过脚本修改数据文件 + udf

    解决问题1:

    创建两张字段类型不同的表(表A的字段类型为varchar,表B的字段类型为bytea)

表B 表A

    往两张表中插入相同的数据(表B做decode处理),再将两张表的结果copy出来,进行比对,发现表B的目标字段和表A的差别在于表B的目标字段前多了\x。对数据文件进行处理,再使用pgloader将数据分别导入表A表B,结果

占用空间的大小

    可以看出空间明显降低,64*(23+1+1+32+8+8)/(23+1+1+64+8+8) 约等于46,符合预期结果。

    解决问题2:

    db集群目前的主要压力在于io,cpu的使用率一直都维持在一个极低的水平。因此,在db层面使用udf来解决insert和select 时数据类型的转换,是一个比较好的选择。相比使用触发器来解决该问题会更加简单,不需要为每个表都定制化触发器,相比使用hook技术也会更加安全可靠。

方案2    通过create type创建一个新类型(待验证)

    postgres支持用户创建一个新的类型。通过自定义输入输出函数(c或其他底层语言编写)以输入函数中将varchar类型转换为bytea的hex格式,在输出函数中将bytea的hex格式转换为varchar格式。

上一篇下一篇

猜你喜欢

热点阅读