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

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

SELECT * FROM TABLE

or

SELECT column1, colum2, column3, etc. FROM TABLE

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

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

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

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


当前回答

结果太大了。从SQL引擎生成结果并将结果发送到客户机的速度很慢。

客户端是一个通用的编程环境,不是也不应该被设计为过滤和处理结果(例如WHERE子句,ORDER子句),因为行数可能非常大(例如数千万行)。

其他回答

对服务器来说,指定列名肯定更快。但是,如果

性能不是大问题(例如,这是一个网站内容数据库,每个表中有数百行,可能是数千行,但不是数百万行);和 你的工作是使用公共框架创建许多小型的类似应用程序(例如面向公众的内容管理网站),而不是创建一个复杂的一次性应用程序;和 灵活性很重要(为每个站点定制大量的db模式);

那么你最好坚持使用SELECT *。在我们的框架中,大量使用SELECT *允许我们将一个新的网站托管内容字段引入到一个表中,赋予它CMS的所有好处(版本控制、工作流/审批等),同时只在几个点上修改代码,而不是几十个点。

我知道DB专家们会因此而恨我——请继续,投我反对票——但在我的世界里,开发人员的时间是稀缺的,而CPU周期是丰富的,所以我相应地调整我所节省的和浪费的。

效率是否重要很大程度上取决于生产数据集的大小(以及它们的增长率)。如果您的数据集没有那么大,也没有那么快地增长,那么选择单个列可能没有太大的性能优势。

随着数据集越来越大,数据增长速度越来越快,性能优势变得越来越重要。

为了以图形方式查看是否有任何不同,我建议使用查询分析器查看SELECT *和等效的SELECT col1、col2等的查询执行计划。这将告诉您两个查询中哪一个更有效。您还可以生成一些不同体积的测试数据,看看时间是什么。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

我发现有些人似乎认为指定列要花费更长的时间。由于您可以将列列表从对象浏览器拖过来,因此在查询中指定列(如果您有很多列,并且需要花费一些时间将它们放在单独的行上)可能需要额外的一分钟时间。为什么人们认为这很耗时呢?

虽然显式列出列对性能有好处,但不要太疯狂。

因此,如果您使用所有数据,为了简单起见,请尝试SELECT *(想象有许多列并执行JOIN…)查询可能会变得很糟糕)。然后,测量。与显式列出列名的查询进行比较。

不要猜测业绩,要衡量业绩!

当你有一些包含大数据的列(比如一篇文章的主体),并且在给定的查询中不需要它时,显式列表是最有用的。然后,通过在应答中不返回它,DB服务器可以节省时间、带宽和磁盘吞吐量。您的查询结果也会更小,这对任何查询缓存都是有利的。