为什么SELECT *是不好的做法?如果您添加了想要的新列,这难道不意味着需要更改的代码更少吗?

我知道SELECT COUNT(*)在某些db上是一个性能问题,但是如果您真的想要每个列呢?


当前回答

如果您将字段添加到表中,它们将自动包含在使用select *的所有查询中。这看起来很方便,但它会使您的应用程序变慢,因为您获取的数据比您需要的要多,并且它实际上会在某些时候使您的应用程序崩溃。

在结果的每一行中可以获取多少数据是有限制的。如果向表中添加字段导致结果超过了限制,则在尝试运行查询时将收到错误消息。

这是一种很难发现的错误。您在一个地方做了更改,而在另一个实际上根本不使用新数据的地方它就会崩溃。它甚至可能是一个不太常用的查询,以至于在有人使用它之前需要一段时间,这使得将错误与更改联系起来更加困难。

如果指定希望在结果中显示哪些字段,就不会出现这种开销溢出。

其他回答

SELECT语句中的星号“*”是查询中涉及的表中所有列的简写。

性能

简写可能会慢一些,因为:

并不是所有的字段都被索引,这迫使对整个表进行扫描——效率较低 保存到通过线路发送SELECT *的内容可能会导致全表扫描 返回比需要的更多的数据 使用可变长度数据类型返回尾随列会导致搜索开销

维护

当使用SELECT *时:

Someone unfamiliar with the codebase would be forced to consult documentation to know what columns are being returned before being able to make competent changes. Making code more readable, minimizing the ambiguity and work necessary for people unfamiliar with the code saves more time and effort in the long run. If code depends on column order, SELECT * will hide an error waiting to happen if a table had its column order changed. Even if you need every column at the time the query is written, that might not be the case in the future the usage complicates profiling

设计

SELECT *是一个反模式:

查询的目的不那么明显;应用程序使用的列是不透明的 它打破了尽可能使用严格类型的模块化规则。Explicit几乎在所有情况下都更好。

什么时候应该使用“SELECT *”?

如果显式地需要涉及表中的每一列,而不是编写查询时存在的每一列,则使用SELECT *是可以接受的。数据库将在内部将*展开为完整的列列表—没有性能差异。

否则,显式地列出要在查询中使用的每一列—最好是在使用表别名时。

还有一个更实际的原因:钱。当你使用云数据库时,你必须为数据处理付费,没有任何解释来读取你将立即丢弃的数据。

例如:BigQuery:

查询价格 查询定价是指运行SQL命令和用户定义函数的成本。BigQuery根据一个指标对查询收费:处理的字节数。

和控制投影-避免选择*:

最佳实践:控制投影—只查询所需的列。 投影指的是查询读取的列数。投影多余的列会导致额外的(浪费的)I/O和物化(写入结果)。 使用SELECT *是最昂贵的查询数据的方法。当您使用SELECT *时,BigQuery会对表中的每一列进行全面扫描。

如果您将字段添加到表中,它们将自动包含在使用select *的所有查询中。这看起来很方便,但它会使您的应用程序变慢,因为您获取的数据比您需要的要多,并且它实际上会在某些时候使您的应用程序崩溃。

在结果的每一行中可以获取多少数据是有限制的。如果向表中添加字段导致结果超过了限制,则在尝试运行查询时将收到错误消息。

这是一种很难发现的错误。您在一个地方做了更改,而在另一个实际上根本不使用新数据的地方它就会崩溃。它甚至可能是一个不太常用的查询,以至于在有人使用它之前需要一段时间,这使得将错误与更改联系起来更加困难。

如果指定希望在结果中显示哪些字段,就不会出现这种开销溢出。

即使您现在希望选择每一列,也可能不希望在某人添加一个或多个新列之后选择每一列。如果您使用SELECT *来编写查询,那么在某些时候,您可能会冒这样的风险,即有人可能会添加一列文本,从而使您的查询运行得更慢,即使您实际上并不需要该列。

如果您添加了想要的新列,这难道不意味着需要更改的代码更少吗?

如果您确实想要使用新列,那么无论如何您都必须对代码进行大量其他更改。你只保存,new_column -只有几个字符的输入。

在很多情况下,SELECT *会在应用程序的运行时导致错误,而不是在设计时。它隐藏了应用程序中列更改或坏引用的信息。