13 年发现 pg 有了 json 类型,便从 oracle 转 pg,几年下来也算比较熟稔了,总结几个有益的实践。

用途一:存储设计时无法预料的文档性的数据。比如,通常可以在人员表准备一个 json 类型字段,名字叫 info、tag 之类。人员表是系统很难设计的表,常常需要扩充各类信息,如驾照号、社保号等等,在设计时不能全盘考虑到,这些信息的特点是用于登记、检索,但与其它表没有外键关系。有的信息有多个,比如教育经历,包含有中学大学研究生等等。以往需要分出子表或以嵌套表存储,实现复杂,ER 图规模庞大。引入 JSON 类型后,此类嵌套表几乎都可以合并入 JSON 字段。

又如,网站系统的会员信息中需要保存用户的 APP 设置,这类设置取决于设备程序,专属于该会员,可将设置定义为 JSON 类型,具体需要保存什么信息由 APP 自己掌握。以往也将设置定义为文本,文本丢失了结构,不能适应会员有多个设备(会员可能同时拥有 Android、iOS 两种设备)的情形,JSON 类型拥有数据结构,可以表达 {设备类型: 设置:{}}。

可见,JSON 字段就像可以装入大象的冰箱,打开了这道门就可以存储无尽的信息。采用 JSON 字段后,数据库设计阶段只需要考虑主要业务实体之间的结构,抓大放小,设计思路也更清晰而不至于琐碎。我们知道,软件系统是一个生长的过程,很多东西在设计初期都难以预料,考虑再周详也有未尽之处,何况随着系统使用,需求变更,原以为是属性的,可能要改为数组,原以为是 flat 数组的,可能发现要改用对象数组,这些变迁屡见不鲜,如果采用静态设计,Schema 需要反复调整,对于使用SSH 框架进行开发的,每次调整带来的变动更多。JSON 类型使系统设计更能适合系统不断的演变进化。

将嵌套表放在 JSON 字段中,也避免了 JOIN 带来的性能损失。但有时需要从子表进行检索,如需要查询教育经历包含本科的所有人,这种场景还是应当使用子表,或 JSON 信息和子表同时使用,子表仅用于此类需要从子表出发的检索,这种数据冗余是值得的。

用途二:合并表间继承。表间继承关系通常采用“主从表同主键、从表主键外键到主表主键”实现,PG 数据库还有专门的表继承设计。引入 JSON 类型后,不少继承可以取消。例如,之前常用的组织机构与公司、部门、科室为继承关系,以往公司表、部门表、科室表都从组织机构表继承。引入 JSON 后子类表取消,合并到组织机构表,该表通过 TYPE 字段区分是何种类型的组织机构,对于不同类型的TYPE,其 INFO 字段(JSON) 拥有不同的结构。

这是由于 JSON 数据没有固定结构,每个 JSON 对象都是自说明的,都可以拥有自己的结构,不像静态语言的对象只能获得从类型定义规定的结构。

用途三:从功能角度进行更高级别的抽象。

13 年编写过一个 ETL 工具,在异构数据库中间同步数据。该工具需要将源数据库的数据采集到中心,再由中心分发到目标数据库,数据要在中心 进行存储。中心应该是中立于数据的,不应考虑传输的数据是服装信息、药品信息、还是人员信息,其只应具备传输保管能力,不应具备业务知识,如同 TCP 一样,不应理解传输的是视频还是 HTML,不能为传输HTML搞一个TCP,为传输视频另搞一个TCP。

站在 ETL 功能的视角,所传输的内容都可以理解为对象,据此,可将采集到的数据行不识别结构的全部压缩到一个名为 OBJECT 的 JSON 字段。另外在实际使用时还要考虑对象之间的主从依赖关系,在新增数据时,先新增主表行,再新增子表行,在删除数据时反之。因此,还需要记忆所属对象。最终这个转储中心数据表结构如下:

ID    OBJECT     TYPE      PARENT_ID(FK:ID)

该表其它外围字段此处不赘述。

同样,设计流程系统可着眼于工作环节,将工作环节的其它信息,如地点等等压缩进 JSON 字段,根据这条原理我曾设计过一个万能的 task – actor 表结构,将之前若干貌似各不相干的业务合并为前后相续的 task。

activiti 如能用这种思路组织 task 等信息,当可达到更灵活便利的效果。

-----------

d2js 框架高度支持 json 类型数据,数据库的 json 取出即成为编程语言的对象,编程语言的对象也可直接存入数据库,不需要借助 ORM 映射方式,为开发带来了极大便利。

在没有使用 json 前,很多人担心 json 字段是一个整体无法检索。这个担心大可不必,json 字段存储的对象也可对其属性进行检索,并可建立索引。当然,也不是没有缺陷,作为一个整体,在更新时会一次性引发若干索引的更新。但相比得到的优势来说,优势更为明显。

另外,在实践中 pg 应使用 jsonb 字段类型,而不是 json 类型,jsonb 是 9.5 后推出的 binary 方式存储的 json 类型,类似 mongodb 的 bson,而 json 类型是字符串方式存储的,显然 jsonb 更节约空间且效率更高。

pg 提供了不少极有用的 json 操作符和函数,应一一试验做一个接触式了解。

PostgreSQL: Documentation: 9.6: JSON Functions and Operators
https://www.postgresql.org/docs/9.6/static/functions-json.html

PG 中 JSON 字段的应用的更多相关文章

  1. MySQL中JSON字段的使用技巧

    mysql5.7.8之后开始原生支持json. 在类似mongodb这种nosql数据库中,json存储数据是非常自然的, 在mysql中合理的使用json,能够带来极大的便利 Json字段的使用场景 ...

  2. npm的package.json字段含义中文文档

    简介 本文档有所有package.json中必要的配置.它必须是真正的json,而不是js对象. 本文档中描述的很多行为都受npm-config(7)的影响. 默认值 npm会根据包内容设置一些默认值 ...

  3. mysql中,通过json_insert函数向json字段插入键值?json_insert函数的使用?

    需求描述: 通过json_insert向json字段中插入值,在此进行实验,记录下. 操作过程: 1.查看已经有的包含json数据类型的表 mysql> select * from tab_js ...

  4. mysql数据库中,如何对json数据类型的值进行修改?通过json_set函数对json字段值进行修改?

    需求描述: 今天在看mysql中存放json数据类型的问题,对于json数据进行修改的操作, 在此记录下. 操作过程: 1.创建包含json数据类型的表,插入基础数据 mysql> create ...

  5. mysql中,创建包含json数据类型的表?创建json表时候的注意事项?查询json字段中某个key的值?

    需求描述: 在mysql数据库中,创建包含json数据类型的表.记录下,在创建的过程中,需要注意的问题. 操作过程: 1.通过以下的语句,创建包含json数据类型的表 mysql> create ...

  6. Mysql中处理JSON字段

    处理json字段,可以用json_extract函数: select * from (select json_extract(ext_value,'$.high')+0 highx,batch_id ...

  7. mysql 和mssql2016中的json字段相关操作

    Mysql: mysql中有专门的Json字段,不是通用的varchar字段,可以保存key/value对,也可保存value集合. 可以增加.删除.修改Json中的某一字段,查询时可以为条件. 如果 ...

  8. ios中json解析出现的null问题

    http://my.oschina.net/iq19900204/blog/408034 在iOS开发过程中经常需要与服务器进行数据通讯,Json就是一种常用的高效简洁的数据格式. 问题现象 但是几个 ...

  9. easyui datagrid中datetime字段的显示和增删改查问题

    datagrid中datetime字段的异常显示: 使用过easyui datagrid的应该都知道,如果数据库中的字段是datetime类型,绑定在datagrid显式的时候会不正常显示,一般需要借 ...

随机推荐

  1. AC日记——地鼠游戏 codevs 1052

    1052 地鼠游戏  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解       题目描述 Description 王钢是一名学习成绩优异的学生,在平 ...

  2. canvas贝塞尔曲线 - 1

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAvEAAAIcCAIAAADwgGbqAAAgAElEQVR4nOy9a4wb55nn20kOZhq7o8

  3. PAT 1048. 数字加密(20)

    本题要求实现一种数字加密方法.首先固定一个加密用正整数A,对任一正整数B,将其每1位数字与A的对应位置上的数字进行以下运算:对奇数位,对应位的数字相加后对13取余--这里用J代表10.Q代表11.K代 ...

  4. 检索 COM 类工厂中 CLSID 为 {000209FF-0000-0000-C000-000000000046} 的组件时失败,原因是出现以下错误: 80070005

    检索 COM 类工厂中 CLSID 为 {000209FF-0000-0000-C000-000000000046} 的组件时失败,原因是出现以下错误: 80070005 在CSDN上总是有网友问这个 ...

  5. 洛谷P2256 一中校运会之百米跑

    题目背景 在一大堆秀恩爱的**之中,来不及秀恩爱的苏大学神踏着坚定(?)的步伐走向了100米跑的起点.这时苏大学神发现,百米赛跑的参赛同学实在是太多了,连体育老师也忙不过来.这时体育老师发现了身为体育 ...

  6. 常用linux手头命令

    过滤ip ifconfig eth0|grep -oP "([0-9]{1,3}\.){3}[0-9]{1,3}"|sed -n '1p' ifconfig|sed -n '2p' ...

  7. 每天成长一点---WEB前端学习入门笔记

    WEB前端学习入门笔记 从今天开始,本人就要学习WEB前端了. 经过老师的建议,说到他每天都会记录下来新的知识点,每天都是在围绕着这些问题来度过,很有必要每天抽出半个小时来写一个知识总结,及时对一天工 ...

  8. [LeetCode] Insert Delete GetRandom O(1) - Duplicates allowed 常数时间内插入删除和获得随机数 - 允许重复

    Design a data structure that supports all following operations in average O(1) time. Note: Duplicate ...

  9. 【WPF】 通过FarPoint显示Excel

    1.FarPoint 只支持winform,在Wpf中要引用:WindowsFormsIntegration.dll2.*.xaml文件引用    xmlns:wfi ="clr-names ...

  10. 使用SharpPCap在C#下进行网络抓包

    在做大学最后的毕业设计了,无线局域网络远程安全监控策略那么抓包是这个系统设计的基础以前一直都是知道用winpcap的,现在网上搜了一下,有用C#封装好了的,很好用下面是其中的几个用法这个类库作者的主页 ...