PostgreSQL实战:为什么说JSONB是PostgreSQL的杀手级功能?

文章目录

    • 一、JSONB概述
      • 1.1 JSONB的应用场景及功能
      • 1.2 JSON vs JSONB:本质区别
      • 1.3 如何合理设置JSONB类型?
      • 1.4 JSONB的使用建议
      • 1.5 JSONB 未来可能的演进
    • 二、JSONB 基础操作
      • 2.1 创建包含 JSONB 的表
      • 2.2 插入 JSONB 数据
      • 2.3 基本查询
      • 2.4 JSONB 更新与修改
    • 三、JSONB 高级查询
      • 3.1 包含与存在判断
      • 3.2 路径查询:`#>` 与 `#>>`
    • 四、JSONB 函数大全
      • 4.1 结构分析函数
      • 4.2 构造与转换函数
    • 五、JSONB 索引优化:性能的关键
      • 5.1 GIN 索引(最常用)
      • 5.2 表达式索引(针对特定路径)
      • 5.3 多列复合索引
      • 5.4 索引选择建议
    • 六、典型应用场景
      • 6.1 灵活的用户配置表
      • 6.2 API 请求/响应日志
      • 6.3 电商商品动态属性
      • 6.4 事件溯源(Event Sourcing)
    • 七、常见问题与解决方案
      • 7.1 NULL 与 missing key 的区别
      • 7.2 数字 vs 字符串比较
      • 7.3 更新操作的原子性

本文将从基础概念到高级实战,系统性地讲解 PostgreSQL 中JSONB的核心原理、操作语法、性能优化、索引策略及典型应用场景,旨在帮助开发者和 DBA 充分释放 JSONB 的潜力。

一、JSONB概述

1.1 JSONB的应用场景及功能

PostgreSQL 自 9.2 版本引入对 JSON 的原生支持,并在 9.4 版本中重磅推出JSONB(JSON Binary)数据类型,彻底改变了传统关系型数据库处理半结构化数据的方式。如今,JSONB 已成为 PostgreSQL 最具竞争力的特性之一,广泛应用于配置管理、日志存储、API 数据缓存、灵活表结构设计等场景。

与传统的JSON类型不同,JSONB以二进制格式存储数据,支持索引、高效的查询和更新操作,同时保留了完整的 JSON 语义。它既具备 NoSQL 的灵活性,又继承了关系型数据库的 ACID 事务、强一致性、丰富索引和 SQL 表达能力——这正是“多模型数据库”(Multi-model Database)理念的完美体现。

1.2 JSON vs JSONB:本质区别

1、存储格式

  • JSON:以文本形式存储,保留原始输入的格式(包括空格、键顺序、重复键等)。每次读取都需要解析。
  • JSONB:以二进制格式(decomposed binary format)存储,自动去除无意义空格、标准化键顺序、丢弃重复键(仅保留最后一个),读取时无需解析,速度更快。

推荐:除非需要严格保留原始 JSON 字符串(如审计日志),否则一律使用JSONB

2、功能对比

特性JSONJSONB
存储效率低(文本)高(二进制)
查询性能慢(需解析)快(直接访问)
支持索引✅(GIN, BTREE 等)
支持更新操作✅(jsonb_set, `
保留键顺序❌(按字母排序)
保留重复键❌(自动去重)

示例:

SELECT'{"b":2, "a":1}'::json;-- 输出: {"b":2, "a":1}SELECT'{"b":2, "a":1}'::jsonb;-- 输出: {"a": 1, "b": 2}

1.3 如何合理设置JSONB类型?

1、不要滥用 JSONB

  • 适合:结构多变、读多写少、非核心业务字段。
  • 不适合:频繁 JOIN、强约束、高并发更新的字段。

原则:核心实体用关系模型,扩展属性用 JSONB。

2、控制 JSONB 大小

  • 单个 JSONB 字段最大 1GB(受 TOAST 限制),但建议 < 1MB;
  • 过大的 JSONB 会影响 WAL 日志、复制和备份效率。

3、避免深度嵌套

  • 查询深层路径(如a.b.c.d.e)难以索引;
  • 建议扁平化结构,或拆分为多个 JSONB 字段。

4、使用生成列(Generated Columns)

PostgreSQL 12+ 支持基于 JSONB 的生成列,可对其建立普通索引:

ALTERTABLEproductsADDCOLUMNbrandTEXTGENERATED ALWAYSAS(attributes->>'brand')STORED;CREATEINDEXONproducts(brand);

优点:查询WHERE brand = 'Dell'性能接近普通列,且自动同步。

1.4 JSONB的使用建议

JSONB 是 PostgreSQL 融合关系模型与文档模型的杰出成果。它不是要取代传统表结构,而是为那些“结构不确定、变化频繁、查询模式多样”的数据提供了一种优雅的解决方案。

掌握 JSONB,意味着你能在同一个数据库中同时享受 SQL 的强大表达力与 NoSQL 的灵活性。正如 PostgreSQL 官方所言:“You don’t have to choose between relational and document — you can have both.”

建议

  • 小规模项目:大胆使用 JSONB 快速迭代;
  • 大规模系统:结合生成列、合理索引、监控执行计划;
  • 永远记住:好的数据模型 = 关系 + 文档 + 合理边界

1.5 JSONB 未来可能的演进

  • JSON Schema 验证:社区正在推动内置 JSON Schema 支持(目前需通过触发器或外部函数实现)。
  • 向量化执行:未来版本可能优化 JSONB 的批量处理性能。
  • 与 GraphQL 集成:借助graphql-postgres等工具,JSONB 可作为 GraphQL 后端的数据源。

二、JSONB 基础操作

2.1 创建包含 JSONB 的表

CREATETABLEproducts(idSERIALPRIMARYKEY,nameTEXTNOTNULL,attributes JSONB);

2.2 插入 JSONB 数据

INSERTINTOproducts(name,attributes)VALUES('Laptop','{"brand": "Dell", "cpu": "i7", "ram_gb": 16, "tags": ["gaming", "work"]}'::jsonb),('Phone','{"brand": "Apple", "model": "iPhone 15", "color": "black", "in_stock": true}'::jsonb);

注意:可省略::jsonb,PostgreSQL 会自动推断(但显式转换更安全)。

2.3 基本查询

1、查询整个 JSONB 字段

SELECTname,attributesFROMproducts;

2、使用->->>提取值

  • column->'key':返回JSONB类型(可用于嵌套查询)
  • column->>'key':返回TEXT类型(适合显示或比较)
-- 获取品牌(JSONB 类型)SELECTattributes->'brand'FROMproducts;-- 获取品牌(TEXT 类型)SELECTattributes->>'brand'ASbrandFROMproducts;-- 结果: Dell, Apple

3、访问数组元素

-- 获取 tags 数组的第一个元素(JSONB)SELECTattributes->'tags'->0FROMproductsWHEREattributes->>'brand'='Dell';-- 结果: "gaming"-- 转为 TEXTSELECTattributes->'tags'->>0FROMproducts;

4、嵌套对象访问

-- 假设 attributes = {"specs": {"screen": "15inch", "weight_kg": 2.1}}SELECTattributes->'specs'->>'screen'FROMproducts;

2.4 JSONB 更新与修改

JSONB 支持多种方式更新字段,这是其超越传统 JSON 的关键优势。

1、使用||合并

-- 为某产品添加新属性UPDATEproductsSETattributes=attributes||'{"warranty_years": 3}'::jsonbWHEREname='Laptop';

注意:若键已存在,||会覆盖原值。

2、使用jsonb_set精准更新

语法:

jsonb_set(target_jsonb,path_array,new_value,create_missing)
  • create_missing:若路径不存在是否创建(默认true

示例

-- 修改 CPU 型号UPDATEproductsSETattributes=jsonb_set(attributes,'{cpu}','"i9"',false)WHEREattributes->>'brand'='Dell';-- 为无 "discount" 字段的产品添加默认值UPDATEproductsSETattributes=jsonb_set(attributes,'{discount}','0.1',true)WHERENOT(attributes ?'discount');

3、删除键或数组元素

  • 删除键:使用-操作符

    UPDATEproductsSETattributes=attributes-'in_stock';
  • 删除数组元素:需指定索引(不常用,因数组顺序可能变化)

    -- 删除 tags[1]UPDATEproductsSETattributes=jsonb_set(attributes,'{tags}',(attributes->'tags')-1);

更安全的做法是重构为对象或使用应用层处理。

三、JSONB 高级查询

PostgreSQL 提供了丰富的操作符用于复杂查询。

3.1 包含与存在判断

操作符含义示例
@>左侧包含右侧attributes @> '{"brand": "Dell"}'
<@左侧被右侧包含(较少用)
?键是否存在attributes ? 'in_stock'
`?`是否存在任一键(数组)
?&是否包含所有键attributes ?& ARRAY['brand', 'cpu']

示例

-- 查找所有有 "gaming" 标签的产品SELECT*FROMproductsWHEREattributes->'tags'?'gaming';-- 查找包含指定属性组合的产品SELECT*FROMproductsWHEREattributes @>'{"brand": "Apple", "color": "black"}';

3.2 路径查询:#>#>>

用于通过路径数组访问深层嵌套值:

-- 假设 attributes = {"user": {"profile": {"age": 30}}}SELECTattributes#>'{user,profile,age}' FROM logs;-- 返回 JSONB: 30SELECTattributes#>>'{user,profile,age}' FROM logs;-- 返回 TEXT: '30'

路径必须是文本数组,不能动态拼接(但可在函数中构造)。

四、JSONB 函数大全

PostgreSQL 提供大量内置函数处理 JSONB。

4.1 结构分析函数

函数作用
jsonb_each(jsonb)将顶层键值对展开为行(key TEXT, value JSONB)
jsonb_each_text(jsonb)同上,value 为 TEXT
jsonb_object_keys(jsonb)返回顶层所有键(TEXT 集合)
jsonb_array_elements(jsonb)展开 JSON 数组为行
jsonb_array_length(jsonb)返回数组长度
jsonb_typeof(jsonb)返回值类型(“string”, “number”, “boolean”, “object”, “array”, “null”)

示例:展开 tags 数组

SELECTname,tagFROMproducts,jsonb_array_elements_text(attributes->'tags')AStag;-- 结果:-- Laptop | gaming-- Laptop | work

4.2 构造与转换函数

函数作用
jsonb_build_object(key1, val1, ...)构造 JSONB 对象
jsonb_build_array(val1, val2, ...)构造 JSONB 数组
row_to_json(row)/to_jsonb(row)将行转为 JSON
jsonb_strip_nulls(jsonb)移除值为 null 的键

示例:动态构建配置

SELECTjsonb_build_object('user_id',id,'preferences',jsonb_build_object('theme','dark','lang','en'))ASconfigFROMusersLIMIT1;-- 结果: {"user_id": 1, "preferences": {"theme": "dark", "lang": "en"}}

五、JSONB 索引优化:性能的关键

未加索引的 JSONB 查询在大数据量下会非常慢。PostgreSQL 提供多种索引策略。

5.1 GIN 索引(最常用)

适用于@>,?,?|,?&等操作。

-- 对整个 JSONB 字段建 GIN 索引CREATEINDEXidx_products_attributesONproductsUSINGGIN(attributes);-- 查询将走索引SELECT*FROMproductsWHEREattributes @>'{"brand": "Dell"}';

5.2 表达式索引(针对特定路径)

若只查询某个键,可创建表达式索引提升效率:

-- 为 attributes->'brand' 创建 BTREE 索引(适合 =, <, > 比较)CREATEINDEXidx_products_brandONproducts((attributes->>'brand'));-- 或 GIN 索引(适合存在性检查)CREATEINDEXidx_products_tagsONproductsUSINGGIN((attributes->'tags'));

注意:attributes->'tags'是 JSONB 类型,可用 GIN;attributes->>'brand'是 TEXT,用 BTREE。

5.3 多列复合索引

-- 品牌 + 是否在库存CREATEINDEXidx_products_brand_instockONproducts((attributes->>'brand'),(attributes->'in_stock'));

5.4 索引选择建议

查询模式推荐索引
WHERE attr @> '{"k": "v"}'GIN(attr)
WHERE attr->>'k' = 'v'BTREE((attr->>'k'))
WHERE attr->'arr' ? 'x'GIN((attr->'arr'))
多条件组合复合表达式索引

💡 使用EXPLAIN ANALYZE验证索引是否生效。

六、典型应用场景

6.1 灵活的用户配置表

传统方案需为每个配置项建列,扩展困难。使用 JSONB:

CREATETABLEuser_settings(user_idINTPRIMARYKEY,prefs JSONBDEFAULT'{}');-- 设置偏好UPDATEuser_settingsSETprefs=prefs||'{"theme": "dark", "notifications": true}';-- 查询深色主题用户SELECTuser_idFROMuser_settingsWHEREprefs->>'theme'='dark';

6.2 API 请求/响应日志

记录原始请求体,便于调试和重放:

CREATETABLEapi_logs(id BIGSERIAL,endpointTEXT,request JSONB,response JSONB,created_at TIMESTAMPTZDEFAULTNOW());-- 查询某用户的所有请求SELECT*FROMapi_logsWHERErequest @>'{"user_id": 123}';

6.3 电商商品动态属性

不同品类商品属性差异大(手机 vs 衣服):

INSERTINTOproducts(name,category,specs)VALUES('T-Shirt','clothing','{"size": "M", "color": "red", "material": "cotton"}'),('Smartphone','electronics','{"screen_size": 6.1, "battery_mah": 3500}');

前端可根据category动态渲染表单。

6.4 事件溯源(Event Sourcing)

存储事件负载:

CREATETABLEevents(id UUIDPRIMARYKEY,event_typeTEXT,payload JSONB,occurred_at TIMESTAMPTZ);-- 查询用户注册事件SELECTpayload->>'email'FROMeventsWHEREevent_type='user_registered'ANDpayload @>'{"source": "web"}';

七、常见问题与解决方案

7.1 NULL 与 missing key 的区别

  • attributes->'nonexist'返回NULL(JSONB 类型)
  • attributes->>'nonexist'返回NULL(TEXT 类型)

问题:无法区分“键不存在”和“键值为 null”。

解决方案:使用jsonb_typeof或检查键是否存在:

SELECTattributes ?'optional_field'ASkey_exists,attributes->>'optional_field'ASvalueFROMproducts;

7.2 数字 vs 字符串比较

-- 错误:JSONB 中数字 100 与字符串 '100' 不等SELECT'{"price": 100}'::jsonb @>'{"price": "100"}'::jsonb;-- false-- 正确:确保类型一致SELECT'{"price": 100}'::jsonb @>'{"price": 100}'::jsonb;-- true

应用层应保证数据类型一致性。

7.3 更新操作的原子性

jsonb_set||是原子操作,但复杂逻辑需在事务中完成:

BEGIN;-- 先读SELECTattributesFROMproductsWHEREid=1FORUPDATE;-- 应用层修改-- 再写UPDATEproductsSETattributes=...WHEREid=1;COMMIT;

或使用WITH子句在 SQL 内完成:

WITHupdatedAS(SELECTid,jsonb_set(attributes,'{counter}',to_jsonb((attributes->>'counter')::int+1))ASnew_attrFROMproductsWHEREid=1)UPDATEproductsSETattributes=updated.new_attrFROMupdatedWHEREproducts.id=updated.id;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1177789.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机毕业设计hadoop+spark+hive智慧交通 交通客流量预测系统 大数据毕业设计(源码+论文+PPT+讲解视频)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 技术范围&#xff1a;Sprin…

2026年电磁屏蔽材料生产企业Top10,有哪些上榜? - 工业品牌热点

2026年军工装备自主化进程加速推进,电磁兼容与防护领域的屏蔽材料品质、技术适配性已成为决定装备稳定性与作战效能的核心要素。无论是军工电子方舱的密封屏蔽需求、舰载设备的海洋环境防护场景,还是机载系统的轻量化…

基于大数据+Hadoop的电商用户行为预测系统平台的设计与实现开题报告

基于大数据Hadoop的电商用户行为预测系统平台的设计与实现开题报告 一、选题背景与意义 &#xff08;一&#xff09;选题背景 在数字经济高速发展的浪潮下&#xff0c;电子商务行业已成为推动社会经济增长的核心动力之一。随着移动互联网、物联网、人工智能等技术的普及&#x…

详细介绍:React Native 样式系统深度解析:与 CSS 的本质区别

详细介绍:React Native 样式系统深度解析:与 CSS 的本质区别2026-01-18 10:12 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !impor…

强烈安利9个AI论文工具,专科生轻松搞定论文写作!

强烈安利9个AI论文工具&#xff0c;专科生轻松搞定论文写作&#xff01; AI 工具如何让论文写作不再难 对于许多专科生来说&#xff0c;论文写作是一道难以逾越的门槛。从选题到撰写&#xff0c;再到反复修改&#xff0c;每一个环节都可能让人感到力不从心。而随着 AI 技术的不…

告别MinIO!RustFS重构存储范式:93MB镜像撬动EB级数据,GitHub狂揽19K星

告别MinIO!RustFS重构存储范式:93MB镜像撬动EB级数据,GitHub狂揽19K星随着AI与大数据的爆发式增长,非结构化数据存储正面临前所未有的挑战。RustFS作为基于Rust语言开发的高性能分布式对象存储系统,以其卓越性能和…

【Python出海】搞定“小语种”修图:AI 如何自动适配德语的长单词与阿拉伯语的“反向排版”?

Python 多语种翻译 RTL排版 小语种 跨境电商 国际化i18n摘要在跨境电商的“全球卖&#xff08;Global Selling&#xff09;”战略中&#xff0c;非英语国家&#xff08;小语种市场&#xff09;是增长最快的蓝海。然而&#xff0c;将一套英文图转化为德语、泰语或阿拉伯语&#…

2026年优秀的铜贴金骨灰盒,铜镀真金骨灰盒,金属骨灰盒厂家用户好评推荐榜 - 品牌鉴赏师

引言在殡葬用品行业,铜贴金骨灰盒、铜镀真金骨灰盒等金属骨灰盒以其独特的质感、文化内涵和耐用性,逐渐成为众多消费者的选择。为了给广大用户提供客观、公正、专业的产品推荐,我们依据国内相关行业协会公开的数据形…

AtCoder Beginner Contest竞赛题解 | AtCoder Beginner Contest 438

​欢迎大家订阅我的专栏:算法题解:C++与Python实现! 本专栏旨在帮助大家从基础到进阶 ,逐步提升编程能力,助力信息学竞赛备战! 专栏特色 1.经典算法练习:根据信息学竞赛大纲,精心挑选经典算法题目,提供清晰的…

学术探险家的秘密武器:书匠策AI如何重塑本科论文写作新体验

在学术的浩瀚宇宙中&#xff0c;每一位本科生都是怀揣好奇与梦想的探险家。然而&#xff0c;面对论文写作这座“未知山峰”&#xff0c;许多人常因选题迷茫、文献混乱、逻辑断裂而踟蹰不前。如今&#xff0c;一款名为书匠策AI&#xff08;http://www.shujiangce.com&#xff09…

学术探险家装备库:书匠策AI解锁本科论文写作新次元

在学术的浩瀚宇宙中&#xff0c;本科论文写作常被视为一场"孤军奋战"的冒险。面对选题撞车、文献迷航、逻辑混乱、语言生硬等重重迷雾&#xff0c;许多学子困在"学术新手村"难以突围。如今&#xff0c;一款名为书匠策AI官网&#xff08;http://www.shujian…

学术探险家装备库:书匠策AI解锁本科论文写作新次元

在学术的浩瀚宇宙中&#xff0c;本科论文写作常被视为一场"孤军奋战"的冒险。面对选题撞车、文献迷航、逻辑混乱、语言生硬等重重迷雾&#xff0c;许多学子困在"学术新手村"难以突围。如今&#xff0c;一款名为书匠策AI官网&#xff08;http://www.shujian…

思维导图天花板 XMind 2025 一键生成思维导图效率翻倍

XMind 2025 是 XMind 公司推出的旗舰级思维导图工具,以AI 赋能、实时协作、任务管理、跨端同步为核心亮点,打通从思维梳理到成果交付的全流程,是职场办公、教育培训、创意创作等场景的高效生产力工具。 核心功能升级…

2026年浙江口碑好的铜贴金铜寿盒,铜仿古铜寿盒,铜镀仿金铜寿盒厂家选购攻略与推荐 - 品牌鉴赏师

引言在2026年的浙江,铜贴金铜寿盒、铜仿古铜寿盒、铜镀仿金铜寿盒市场呈现出蓬勃发展的态势。为了给消费者提供一个客观、公正的厂家选购参考,我们依据一系列科学的测评方法和权威数据,对市场上的相关厂家进行了深入…

【视觉黑科技】1688 原图太糊怎么办?揭秘 AI 如何在批量翻译的同时实现“4K 画质重塑”?

Python 超分辨率 Super-Resolution 图像增强 跨境电商 Real-ESRGAN摘要在跨境电商选品中&#xff0c;优质的供应链往往伴随着劣质的视觉素材。很多 1688 工厂提供的图片分辨率低、压缩噪点多&#xff0c;直接翻译后上传到 Amazon 或 TikTok 会导致“放大镜”功能失效&#xff0…

java-SSM388的在线考试答疑系统vue-springboot

目录具体实现截图系统架构与技术栈核心功能模块关键技术实现创新性与应用价值系统所用技术介绍写作提纲源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;具体实现截图 系统架构与技术栈 该系统采用前后端分离架构&#xff0c;前端基于V…

【网页禁止右键和F12】

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"…

盘点口碑好的镁质风管品牌厂家,温州合胜优势突出! - 工业品牌热点

本榜单依托全维度市场调研与真实行业口碑,深度筛选出五家标杆镁质风管服务商,为建筑工程、消防通风领域的企业选型提供客观依据,助力精准匹配适配的合作伙伴。 TOP1 推荐:温州合胜通风设备有限公司 推荐指数:★★…

java-SSM390考研信息查询系统vue-springboot

目录具体实现截图系统概述技术架构核心功能创新点应用价值系统所用技术介绍写作提纲源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;具体实现截图 系统概述 Java-SSM390考研信息查询系统基于Vue.js与Spring Boot框架开发&#xff0c;旨…

如何环境学习 AI Agent?一篇文章带你走通全流程(附学习路径 资料推荐)

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …