PostgreSQL 13行存储模式下,用*与显式写全字段的性能差异对比
在PostgreSQL 13行存储模式下,SELECT * 与显式指定所有字段的性能差异
在PostgreSQL 13的行存储表中,当你需要查询全部字段时,SELECT * 和显式写出所有字段名的性能差异主要集中在以下几个场景:
1. 查询解析阶段的开销差异
PostgreSQL 在处理 SELECT * 时,必须先查询系统表 pg_attribute,获取当前表的所有用户可见字段列表,并按照字段定义的顺序排序,才能生成最终的查询计划。这个过程对于字段数量较多的表(比如几十甚至上百个字段)会额外增加解析时间——尤其是在频繁执行这类查询的场景下,累积的开销会更明显。
而显式指定所有字段名时,解析器直接使用你给出的字段列表,无需访问系统表查询元数据,解析阶段的耗时会更短。
2. 执行计划的稳定性差异
如果后续表结构发生变更(比如新增字段),SELECT * 会自动将新字段纳入查询范围,这可能导致原本高效的执行计划失效:
- 例如,原本查询使用了覆盖索引(包含所有原字段),新增字段后,
SELECT *需要读取堆中的新字段,被迫放弃覆盖索引转而回表查询,性能会出现明显下降。 - 显式指定所有字段的话,除非你主动将新字段加入查询列表,否则执行计划不会受表结构变更影响,性能保持稳定。
3. 数据重组的微小开销(字段顺序不一致时)
如果你显式指定的字段顺序和表存储的字段定义顺序不一致,PostgreSQL 在返回结果前需要重新排列字段顺序,这会产生少量的CPU开销。而 SELECT * 始终按照表定义的字段顺序返回,无需额外重组,在字段数量极多的场景下,这个差异会被放大。
4. 隐藏字段的读取差异
默认情况下,SELECT * 不会返回系统隐藏字段(比如 oid、ctid、xmin、xmax)。如果你显式指定所有字段时包含了这些隐藏字段,查询会额外读取这些数据,导致数据传输量增加,性能有所下降;反之,若显式指定的仅为用户定义字段,则与 SELECT * 的数据读取量一致。
总结
- 对于字段较少的小表,两种写法的性能差异几乎可以忽略。
- 对于字段较多、查询频繁或表结构可能变更的场景,显式指定所有字段名在解析效率、执行计划稳定性上更有优势。
- 如果你的查询确实需要所有字段,且表结构长期稳定,
SELECT *的性能劣势并不显著,但显式写法的可读性和可维护性更优。
内容的提问来源于stack exchange,提问作者Yuseferi
相关产品推荐
相关产品推荐

