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. Salesforce Apex 开发环境设置和Hello World示例

    本文介绍了Salesforce Apex开发环境的设置以及一个简单的Hello World示例的实现过程. Salesforce开发环境 Salesforce通过http://developer.fo ...

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

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

  3. Linux 进程与线程五

    pthread_self函数 pthread_t pthread_self(void); 一般会成功,返回当前线程的ID 注意:在子线程中执行exit()函数会退出整个进程,一般使用pthread_e ...

  4. C#调用天气查询服务

    先引入天气查询服务 1.有点引用导入服务引用 //实例化            web引用名.WeatherWebService cn = new web引用名.WeatherWebService() ...

  5. dubbox升级spring到4.x及添加log4j2支持

    今天花了点时间,把dubbox依赖的spring从3.x升级成最新版的4.x了,其它一些依赖的组件也顺带升级了,同时dubbo支持的第三方日志组件居然没有log4j2,加了点代码也一并支持了,蛋疼的是 ...

  6. 动态生成验证码———MVC版

    上面有篇博客也是写的验证码,但那个是适用于asp.net网站的. 今天想在MVC中实现验证码功能,弄了好久,最后还是看博友文章解决的,感谢那位博友. 首先引入生成验证码帮助类. ValidateCod ...

  7. RedisUtil 工具类

    package com.test; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import red ...

  8. FragmentTabHost简单保存状态的方法

    private View rootView;@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container ...

  9. [转]Java中导入、导出Excel

    原文地址:http://blog.csdn.net/jerehedu/article/details/45195359 一.介绍 当前B/S模式已成为应用开发的主流,而在企业办公系统中,常常有客户这样 ...

  10. vue.js 第二课

    实现响应的数据绑定和组合的视图组件. 让数据与Dom保持同步 . 在使用jq手工操作DOM时,我们的代码常常是命令式的.重复的.易错的.Vue.js拥抱数据驱动的视图概念.简单的讲,它意味着我们在普通 ...