打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
SELECT * 有多慢?(深入探讨)

在行存储的数据库引擎中,数据以称为页的单元进行存储。每个页都有一个固定的头部,并包含多个行,每个行都有一个记录头部,后面跟着各自的列。例如,在 PostgreSQL 中考虑以下示例:

当数据库获取并将页面放入共享缓冲池时,我们可以访问该页面中的所有行和列。因此,问题出现了:如果我们在内存中已经有了所有列,为什么 SELECT * 会变得如此缓慢和昂贵?它真的像人们所说的那样慢吗?如果确实如此,为什么会这样?在本文中,我们将探讨这些问题和更多内容。

拥抱索引扫描

使用 SELECT * 意味着数据库优化器无法选择索引扫描。 例如,假设您需要获得分数超过90分的学生的ID,并且您在分数列上有一个包括学生ID作为非键的索引,这个索引非常适合此查询。

然而,由于您请求了所有字段,数据库需要访问堆数据页以获取其余字段,从而增加了随机读取,导致更多的输入/输出操作。相比之下,如果您没有使用 SELECT *,数据库只需扫描分数索引并返回ID就可以了。

反序列化成本

反序列化,或解码,是将原始字节转换为数据类型的过程。这涉及将一系列字节(通常来自文件、网络通信或其他来源)转换回更结构化的数据格式,例如编程语言中的对象或变量。

当执行 SELECT * 查询时,数据库需要对所有列进行反序列化,即使您在特定用例中可能不需要这些列。这会增加计算开销并降低查询性能。通过仅选择必要的列,您可以减少反序列化成本,并提高查询的效率。

并非所有列都是内联的

SELECT * 查询的一个重要问题是,并非所有列都以内联方式存储在页面中。大型列,例如文本或大型二进制对象(blob),可能存储在外部表中,并在请求时才检索(例如Postgres的TOAST表)。这些列通常被压缩,因此当您执行带有许多文本字段、几何数据或大型二进制对象的 SELECT * 查询时,会增加数据库的负载,以从外部表中获取值,解压缩它们,并将结果返回给客户端。

网络开销

在将查询结果发送给客户端之前,它必须按照数据库支持的通信协议进行序列化。需要序列化的数据越多,CPU 的工作量就越大。在字节序列化之后,通过 TCP/IP 进行传输。需要发送的分段越多,传输的成本就越高,最终影响网络延迟。

返回所有列可能需要对大型列进行反序列化,例如字符串或二进制大对象 (BLOBs),而客户端可能永远不会使用这些列。

客户端反序列化

客户端一旦接收到原始字节,客户端应用程序必须将数据反序列化为客户端使用的编程语言,这增加了整体处理时间。数据传输的量越大,这个过程就越慢。

总结

总而言之,SELECT * 查询涉及许多复杂的过程,因此最好只选择需要的字段,以避免不必要的开销。请记住,如果您的表只有少数具有简单数据类型的列,则 SELECT * 查询的开销可能可以忽略不计。然而,通常最好在查询中明确选择要检索的列。

同学合作的 ChatGPT 课程,有需要的自取。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
千万不要给女朋友解释 什么是 “二叉树算法”
【数据库优化】记一次Mysql的优化经历
Sql Server查询性能优化之不可小觑的书签查找
MySQL单表百万数据记录分页性能优化
mysql中EXPLAIN 的作用
索引介绍
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服