第一时间收到文章更新
出处:Bytebase(ID:Bytebase)
原文地址 https://x.com/hnasr/status/1856745402399359315
尽量避免 SELECT *,即使在单列表上也是如此 -- 如果你现在不同意这一点,读完这篇文章,你可能就要动摇了。
2012年的一个故事
这是我 12 年前(约 2012-2013 年)在客户后台应用程序中遇到的一个真实故事。
当时,后端 API 一直稳定运行,速度仅为个位数毫秒。但突然有一天,应用程序变得非常迟钝。
我们检查了提交,没发现明显的问题,大部分改动都是良性的。即使恢复了所有提交(有人会懂,作这样无意义的尝试,就说明走投无路了),程序仍然很慢,API 响应时间从原先的几毫秒暴增到 500 毫秒至 2 秒不等。
鉴于后台没有导致速度变慢的变更,我们检查了数据库查询,发现 3 个具有超大文件的 blob 字段,它们表上的 SELECT * 正在返回到后台应用程序。
原来,这个表只有两个整数列,API 运行 SELECT * 来返回并使用这两个字段。但后来管理员添加了三个 blob 字段,由另一个应用程序使用和填充。这些 blob 字段没有返回给客户端,后端 API 却需要拉取其他应用程序填充的额外字段,造成数据库、网络和协议序列化开销。
客户端收到原始字节后,应用程序必须将数据反序列化为客户端使用的任何语言,增加了整体处理时间。管道中的数据越多,这一过程就越慢。
即使只有一个字段,在客户端使用 SELECT * 也会带来不可预测性。
例如,对于含一到两个字段的表,程序会执行 SELECT * 快速处理两个整数字段;但是一旦添加 XML、JSON、blob 等新字段,它们就会被其他应用程序填充和使用。代码没有变化,但速度会突然变慢,因为现在程序要处理所有额外的字段。
显式 SELECT 的另一个优点是,可以在代码库中搜索正在使用的列,以防要重命名或删除某个列。这使得数据库 schema 变更(DDL)更加容易。
总之,SELECT * 查询涉及许多复杂的过程,最好只选择需要的字段,以避免无谓的开销。如果表中的列很少,数据类型简单,SELECT * 查询的开销也许可以忽略不计;但一般来说,在查询中选择性地检索列是一种更好的做法。
推荐阅读:
推荐阅读: