执行三重join查询的最优性能设置:直接查询还是创建数据库视图
性能对比结论及优化建议
两个方案的性能差异
- 如果你用的是MySQL、PostgreSQL等数据库的普通非物化视图,两个方案性能几乎没有差异,方案1甚至略优。
普通视图本质只是预存的SQL查询定义,不会提前缓存计算结果,你基于3个视图执行查询时,数据库优化器最终生成的执行计划和方案1的原生SQL完全一致,不会带来性能提升,反而多创建视图只会增加不必要的元数据维护成本,对个人项目属于冗余操作。 - 只有你使用物化视图(需要手动刷新/定时刷新预存计算结果)的情况下,方案2才会有性能优势,但这种方案需要额外维护视图的刷新逻辑,对于数据量不大的个人项目完全没有必要。
比两个方案性能更优的写法
你现有的方案需要对bills表做两次独立扫描,其实可以用条件聚合把两次扫描合并为一次,IO成本直接降低一半,性能明显优于你提到的两个方案,示例SQL如下:
SELECT u.id, u.name, MAX(CASE WHEN b.status = 'paid' THEN b.month END) AS last_month_paid, MIN(CASE WHEN b.status = 'pending' THEN b.month END) AS last_month_pending FROM users u LEFT JOIN bills b ON u.id = b.id GROUP BY u.id, u.name
额外优化建议
可以给bills表创建联合索引 (id, status, month),这个索引可以覆盖查询需要的所有字段,避免查询时回表查数据,性能还能再提升30%~50%。
如果你的汇总逻辑需要在多个业务逻辑里复用,可以把上面这条优化后的SQL封装成1个汇总视图即可,不需要拆成3个视图,后续调用时直接查这个视图,和直接执行原生SQL性能一致,还能减少重复代码的维护成本。
内容的提问来源于stack exchange,提问作者manolix
相关产品推荐
相关产品推荐

