我听说在编写SQL命令时使用SELECT *通常是不好的做法,因为选择您特别需要的列会更有效。

如果我需要选择表中的每一列,我应该使用

SELECT * FROM TABLE

or

SELECT column1, colum2, column3, etc. FROM TABLE

在这种情况下,效率真的重要吗?如果你真的需要所有的数据,我认为SELECT *在内部会更优,但我这么说并没有真正理解数据库。

我很好奇在这种情况下最好的做法是什么。

更新:我可能应该指定,我真正想要执行SELECT *的唯一情况是,当我从一个表中选择数据时,我知道总是需要检索所有列,即使添加了新列。

然而,鉴于我所看到的反应,这似乎仍然是一个坏主意,由于我曾经考虑过的许多技术原因,SELECT *不应该被使用。


当前回答

这是一个老帖子,但仍然有效。作为参考,我有一个非常复杂的查询,包括:

12个表 6左连接 9个内连接 12个表共108列 我只需要54列 一个4列的Order By子句

当我使用Select *执行查询时,平均花费2869ms。 当我使用Select执行查询时,平均花费1513ms。

返回的总行数为13,949。

毫无疑问,选择列名意味着比Select *更快的性能

其他回答

每次都定义你想要SELECT的列。没有理由不这样做,性能的提高是非常值得的。

他们不应该给“SELECT *”选项

对于直接查询DB(例如通过sqlplus提示符或通过DB管理工具),选择*通常很好——它省去了写出所有列的麻烦。

另一方面,在应用程序代码中最好枚举列。这有几个好处:

代码更清晰 你将知道结果返回的顺序(这对你来说可能重要,也可能不重要)

The SELECT * might be ok if you actually needed all of the columns - but you should still list them all individually. You certainly shouldn't be selecting all rows from a table - even if the app & DB are on the same server or network. Transferring all of the rows will take time, especially as the number of rows grows. You should have at least a where clause filtering the results, and/or page the results to only select the subset of rows that need to be displayed. Several ORM tools exist depending on app language you are using to assist in querying and paging the subset of data you need. For example, in .NET Linq to SQL, Entity Framework, and nHibernate all will help you with this.

考虑到您正在选择所有列的规范,此时没有什么不同。但是,要意识到数据库模式确实会发生变化。如果您使用SELECT *,您将获得添加到表中的任何新列,即使您的代码很可能不准备使用或显示这些新数据。这意味着您正在将系统暴露给意外的性能和功能更改。

你可能会认为这是一个很小的开销,但要意识到你不需要的列仍然必须是:

从数据库读取 通过网络发送 编组到流程中 (适用于adotype技术)保存在内存中的数据表中 忽略和丢弃/垃圾收集

第1项有许多隐藏的成本,包括消除一些潜在的覆盖索引,导致数据页负载(和服务器缓存抖动),引发行/页/表锁,这些锁本来是可以避免的。

将此与指定列而不是*的潜在节省进行平衡,唯一潜在的节省是:

程序员不需要重新访问SQL来添加列 SQL的网络传输更小/更快 SQL Server查询解析/验证时间 SQL Server查询计划缓存

对于第1项,实际情况是,您将添加/更改代码以使用您可能添加的任何新列,因此这是徒劳的。

对于第2项,这种差异很少足以使您使用不同的数据包大小或网络数据包数量。如果SQL语句传输时间是主要问题,那么可能首先需要降低语句的速率。

对于第3项,没有任何节省,因为无论如何都必须展开*,这意味着无论如何都要咨询表的模式。实际上,列出列也会产生相同的成本,因为它们必须根据模式进行验证。换句话说,这完全是一笔勾销。

对于第4项,当您指定特定列时,您的查询计划缓存可能会变大,但只有当您处理不同的列集时(这不是您所指定的)。在这种情况下,您确实需要不同的缓存条目,因为您需要根据需要使用不同的计划。

因此,由于您指定问题的方式,这一切都归结为面对最终模式修改时的问题弹性。如果您正在将这个模式刻录到ROM(这种情况会发生),那么*是完全可以接受的。

但是,我的一般指导原则是,您应该只选择您需要的列,这意味着有时看起来像是您在请求所有这些列,但是dba和模式演变意味着可能会出现一些可能会极大地影响查询的新列。

我的建议是你应该总是选择特定的列。记住,你会不断擅长你所做的事情,所以要养成正确做这件事的习惯。

如果您想知道为什么模式可以在不更改代码的情况下更改,可以考虑审计日志、有效/过期日期和dba系统地添加的其他类似内容,以解决遵从性问题。另一个幕后更改的来源是系统中其他地方或用户定义字段的性能反规范化。

如果记录要遍历internet,那么限制返回的列可以大大提高性能。