为何SELECT指定列比SELECT *的数据库查询速度更快?
你提到的数据库以page为单位读取、整行存储的机制完全正确,但SELECT指定列更快的核心原因在于读取page之后的各个环节都能大幅减少开销,具体可以拆解为这几个关键点:
数据传输与序列化成本大幅降低
数据库确实会把整个page加载到内存,但返回结果时,SELECT指定列只需要提取你需要的字段进行打包,而SELECT *要处理并传输整行的所有字段。比如一行包含大文本、BLOB这类占用空间大的字段时,SELECT *的传输量会是指定列的数倍甚至数十倍——不管是数据库内部的内存拷贝,还是客户端与数据库之间的网络传输,这个开销差距都非常直观。覆盖索引的高效复用
查询指定列时,往往可以触发覆盖索引(Covering Index)。这种索引只包含查询所需的列(加上必要的主键/唯一键),体积比存储整行的数据页小很多:比如一个8KB的数据页只能存3行整行数据,对应的覆盖索引页可能能存30行以上。数据库直接读取索引页就能获取结果,不需要再回表读取数据页,磁盘IO次数和耗时会大幅减少。而SELECT *几乎无法利用覆盖索引,必须读取完整的数据页。内存缓存利用率提升
数据库的内存缓存(比如PostgreSQL的shared_buffers)容量有限。如果只加载查询需要的列(或覆盖索引),缓存中能容纳更多的有效数据,后续相同或相似查询的缓存命中率会更高,减少重复的磁盘读取操作。而SELECT *会把整行数据都存入缓存,占用更多空间,导致缓存可容纳的其他数据减少,命中率下降,后续查询更容易触发磁盘IO。CPU处理开销减少
从行数据中筛选指定列的CPU开销,远小于处理、序列化整行数据的开销。数据库需要对每个字段进行类型转换、格式处理,SELECT *要处理所有字段,而指定列只处理部分,CPU使用率更低,响应速度自然更快。
内容的提问来源于stack exchange,提问作者Patrick

