PostgreSQL存储用餐记录是否应将timestamp的时间部分提取为json类型?
问题1:用户录入餐食时,哪种方案的响应速度更快?
优先选原始的meals表方案,绝大多数场景下录入速度更快,原因如下:
- 每次用户录入餐食时,
meals表只需要执行单行INSERT操作,属于追加写,不需要读取旧数据,也没有额外的行锁竞争,开销极低。 meals_of_day方案如果是用户当日第二次及以后录入餐食,需要先查询是否存在当日的对应记录,再执行UPDATE操作修改records字段,哪怕用性能更好的jsonb类型,更新也需要读取、修改、回写整段json内容,开销远高于单行插入;如果同一用户短时间内多次录入,还会产生行锁竞争,进一步拖慢响应。- 只有当你是一次性批量录入用户全天所有用餐记录的场景下,
meals_of_day的单次写入速度可能略快,但这种场景占比极低。
问题2:若分析功能包含大量时间相关查询,哪种方案效率更高?
还是meals表方案效率更高,优势非常明显:
- 你只需要给
meals表建立user_id + timestamp的联合索引,所有按用户、按时间范围的过滤都可以直接走索引,比如查询某用户过去一个月的用餐记录、统计全平台每周的用餐高峰时段这类需求,都可以直接通过索引快速过滤数据,不需要额外解析操作。 - 统计聚合的成本极低:比如要统计用户每月吃肉类的次数、平均用餐时间这类需求,直接对表字段做聚合计算即可,
labels字段如果用PostgreSQL原生数组类型存储,还可以建GIN索引加速标签过滤,性能远高于json内部字段查询。 meals_of_day方案做时间相关分析时,需要先把records字段的json内容用jsonb_each等函数炸开,逐行解析json结构、提取时间和属性字段,完全走不了索引,数据量稍大就会出现严重的性能问题,后续如果要新增字段做统计,还要调整所有json的内部结构,维护成本也极高。
内容的提问来源于stack exchange,提问作者Xullnn
相关产品推荐
相关产品推荐

