关联数组存入数据库方案咨询:序列化存储还是逐行存储更优
首先明确结论:你提到的序列化后存Blob的方案不是最优实现,绝大多数场景下远不如原来的逐行存储方案。
两种方案的对比
序列化存Blob方案的优劣势
唯一的优势仅为查询单个用户全量答题记录时仅需读取1行,表面上减少了IO次数,但缺点远大于收益:
- 完全不支持细粒度查询:如果后续需要统计某道题的作答分布、查询某道题有哪些用户选了特定答案、校验某用户是否作答过指定题目,你必须把全表所有Blob数据读出来反序列化后逐行遍历,数据量稍大时性能比逐行存储低10倍以上。
- 无法保障数据一致性:原来的逐行存储可以通过外键约束
answer_id、question_id的合法性,序列化后的数据完全依赖业务代码校验,很容易产生脏数据。 - 额外的序列化/反序列化开销:PHP的
serialize()输出有大量格式冗余,20道题的数组压缩比例极低,反而每次读写都要额外消耗CPU做序列化处理,整体性能没有提升。 - 扩展能力极差:后续如果需要给单条答题记录加作答时间、是否修改过、单题得分这类附加字段,数组结构的兼容成本极高,老数据批量处理难度远大于逐行存储。
原逐行存储方案的优劣势
原user_answers的多对多结构完全符合数据库设计三范式,是绝大多数业务场景的最优选择:
- 灵活支持所有查询场景:只要给
user_id、question_id、answer_id加上对应索引,无论是查单个用户的所有作答,还是统计单题的作答分布,性能都非常优秀,单用户20条记录对于MySQL来说完全没有性能压力,你担心的性能问题纯属过度优化。 - 支持数据库层面的一致性校验,后续扩展字段成本极低,加列即可实现。
更合适的数组类字段选择
如果你100%确认业务不会有任何细粒度查询、统计需求,仅需要存储单用户全量答题结果,也不要用序列化+Blob的方案,优先选择以下类型:
- MySQL 5.7及以上版本:使用
JSON字段存储数组,原生支持SQL层面的JSON内容查询,还可以给JSON内的字段创建虚拟索引提升查询性能,内容可读性强,跨语言兼容,空间占用也比序列化Blob更小。 - PostgreSQL:可以选择原生
ARRAY类型或者JSONB类型,JSONB支持GIN索引,查询性能接近逐行存储的水平。
最终建议
但凡业务存在统计分析、后续扩展的可能性,直接保留原来的逐行存储方案即可,性能和维护性都远优于序列化存Blob的方案。如果确实仅需要全量读写单用户答题记录,用JSON字段替代序列化Blob即可。
内容的提问来源于stack exchange,提问作者user_411
相关产品推荐
相关产品推荐

