JSONB应用场景
PostgreSQL中有2种和json相关的数据类型,json和jsonb,本文指的是jsonb, 也推荐大家使用jsonb。
假设一张表所有的记录都有属性 attr1..attr10,但只有部分记录存在attr11..attr20属性,同时后续还有可能增加 attr21, attr22,这个时候创建一个包含json列的表就非常合适。
create table t1 (attr1 numeric, attr2 int, .. attr10 text, extra jsonb);
attr11..attr20 的数据作为k-v对存储在extra属性内。 如果将来有了 attr21, attr22,直接存放到 extra 属性内即可,完全不需要对表结构进行修改。
除了使用json数据类型,还有其他的解决方案可以尝试。比如将 extra 设置为一个 text / binary 类型,由在客户端进行序列化和反序列化。 这种方式的缺陷在于需要将数据传输到客户端才能进行运算,无法使用更为先进的各种扫描方式,也增大了网络的传输量, 而使用json/jsonb就完全没有这类问题。
select extra->'attr11' from t1 where extra->>'att20' = 'apple';
我们可以在服务端进行数据的过滤和投影,减少了网络的传输量。 同时也可以在 extra->>'att20' 创建索引,来加速过滤条件。
另外一种极端设计是将所有的属性存放到一个jsonb类型中, 创建如下的表结构:
create table t2(data jsonb)
这个方案也不是最优的,因为对于所有的记录都需要重复记录attr1, attr10的属性,比如同一行数据,t1 和 t2 的存储方式分别如下:
t1: 1|2|3|..|'20'|{'attr21': 2, 'attr22': 3} t2: {'attr1': 1, 'attr2': 2, 'attr3': 3, ... 'attr21': 2, 'attr22': 3}
t2 的设计方式会带来存储和网络传输上的开销。 这两个问题都可以通过压缩来缓解,但压缩/解压本身也是有代价的。
允许同时使用jsonb数据类型和传统数据类型是PostgreSQL的一大特色,灵活使用这个能力可以带来极大的好处。 继续上面的案例:假设后来我们发现 attr11 对于所有的记录都存在, 我们完全可以将表结构改成
create table t1 (attr1 numeric, attr2 int, .. attr10 text, attr11 text, extra jsonb);
随后应用程序再做少量的改变就可以。相比较于一开始选择了仅支持文档型的数据库来说,这种修改不需要应用程序增加新的数据源, 不需要管理新的连接,只需要修改一下 attr11的访问方式即可。
Shared Detoast Datum能力
对于一个json的数据类型来说,数据稍微大一些就会使用到toast能力。 拿t1的数据来说,大致的工作原理可以简化为:
t1: 1|2|3|..|{pointer-x} pg_toast_{t1} pointer-x| 1 | {attr11:.., attr12: ...} pointer-x| 2 | {attr16:.., attr20: ...}
只有当我们需要访问 pointer-x 的真实的值的时候,我们“才” 组装出来 {attr11: 11, ..., attr20: 20} 的值,而组装的过程被称之为detoast, 这个组装的过程也是比较消耗资源的。 关于toast 更为详细的介绍请参考: https://zhuanlan.zhihu.com/p/142281841
对于如下SQL:
select extra->'attr11' from t1 where extra->>'att20' = 'apple';
extra->>'att20' 和 extra->'attr11' 都需要访问完整的extra数据,在原生的PostgreSQL中会进行detoast 2次。而下面的语句就会detoast 4次。当extra稍微大一些,大量的时间都是消耗在了detoast环节了。而shared detoast datum就是为了解决这个问题而设计的,对于同一个数据,我们只会detoast一次。 shared detoast datum的能力会在阿里云PolarDB-PG14的4月份的版本中发布。
select extra->'attr11', extra->'attr12' from t1 where extra->>'att20' = 'apple' and extra->>'attr19' = 'cloud';
PolarDB PG简介
PolarDB PostgreSQL版(简称PolarDB-PG)是一款阿里云自主研发的云原生关系型数据库产品,100% 兼容 PostgreSQL,高度兼容Oracle语法(公有云版支持Oracle语法);采用基于 Shared-Storage 的存储计算分离架构,具有极致弹性、毫秒级延迟、HTAP 的能力和高可靠、高可用、弹性扩展等企业级数据库特性。同时,PolarDB 具有大规模并行计算能力,可以应对OLTP与OLAP混合负载。
作者介绍
樊智辉,花名 一挃,阿里云PolarDB PG产品优化器方向负责人,致力于为用户提供更好的PostgreSQL服务。