Hubert 'depesz' Lubaczewski:旧技术有时更好——基于 Now-Next 博客文章的案例研究……
内容提要
通过PostgreSQL实验比较变更日志记录方式:JSONB记录整行耗时920毫秒、占用42MB,记录差异耗时1430毫秒、占用15MB;hstore记录整行耗时829毫秒、占用39MB,记录差异耗时798毫秒、占用14MB。结果表明hstore比JSONB更快、更省空间,更适合表变更日志。
延伸解读
测试环境与数据规模
文章基于一张包含10万行的表进行测试,表结构包含id、ts、b、title、i等字段。更新操作模拟了批量修改,其中约60%的行会改变ts和i值。测试对比了无日志、JSONB全行、JSONB差异、hstore全行和hstore差异五种方式,每种方式重复三次取最佳时间,以降低随机波动影响。
性能与空间对比
在相同更新下,无日志耗时约238毫秒。JSONB全行记录耗时约921毫秒、占用42MB,差异记录耗时约1430毫秒、占用15MB。hstore全行记录耗时约830毫秒、占用39MB,差异记录耗时约798毫秒、占用14MB。可见hstore在速度和空间上均优于JSONB,且差异记录比全行记录更快。
差异记录的实现差异
JSONB差异记录通过jsonb_each和jsonb_object_agg逐键比较,逻辑较复杂,导致速度反而比全行记录慢。hstore则利用其减法操作符直接计算差异,代码更简洁,执行更快。这解释了为何hstore差异记录能比全行记录更快,而JSONB差异记录却更慢。
适用场景与局限
作者强调hstore并非在所有场景都优于JSONB,但在表变更日志这一特定用途上,hstore更简单、更快且占用磁盘略少。需要注意的是,测试仅针对单表更新,未涵盖插入、删除或复杂数据类型,实际选择时仍需结合具体需求评估。
Q&A
在PostgreSQL中,使用JSONB记录表变更日志时,记录整行和记录差异的性能和空间占用分别是多少?
根据文章中的实验,使用JSONB记录整行耗时920.846毫秒,占用42,262,528字节;记录差异耗时1430.001毫秒,占用15,843,328字节。
使用hstore记录表变更日志时,记录整行和记录差异的性能和空间占用分别是多少?
使用hstore记录整行耗时829.950毫秒,占用39,780,352字节;记录差异耗时798.260毫秒,占用14,704,640字节。
为什么说hstore比JSONB更适合用于表变更日志?
因为实验表明hstore比JSONB更快(记录整行和差异的耗时都更短),占用磁盘空间也更少,并且使用hstore时记录差异比记录整行更快,而JSONB则相反。
如何用PostgreSQL触发器实现只记录变更列的日志?
可以使用触发器函数,通过比较OLD和NEW的JSONB表示,利用jsonb_each和jsonb_object_agg筛选出发生变化的键值对,然后插入到日志表中。文章提供了具体的函数代码示例。
在PostgreSQL中,使用hstore记录变更日志时,如何编写触发器函数?
首先创建hstore扩展,然后定义触发器函数,将OLD和NEW转换为hstore类型,对于差异日志,使用hstore减法操作符(o - n 和 n - o)获取变化的键值对,然后插入到日志表中。文章提供了完整的代码示例。
文章中的性能测试是如何进行的?
测试使用了一个包含10万行的表,执行批量更新(更新ts和i列),分别测试了无日志、JSONB整行日志、JSONB差异日志、hstore整行日志和hstore差异日志。每次测试都重新创建表,重复3次取最佳时间,并记录日志表的大小。