关于sql:哪个更快/最好? SELECT *或SELECT column1,colum2,column3等

关于sql:哪个更快/最好? SELECT *或SELECT column1,colum2,column3等

Which is faster/best? SELECT * or SELECT column1, colum2, column3, etc

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

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

1
SELECT * FROM TABLE

要么

1
SELECT column1, colum2, column3, etc. FROM TABLE

在这种情况下,效率真的重要吗? 我认为,如果您确实需要所有数据,则SELECT *在内部会更理想,但是我说的是这并没有对数据库的真正了解。

我很好奇这种情况下的最佳做法。

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

但是,鉴于我所看到的答复,这似乎仍然是一个坏主意,并且出于很多技术上的原因,切勿使用SELECT *


选择特定列更好的原因之一是,它增加了SQL Server可以从索引访问数据而不是查询表数据的可能性。

这是我写的一篇文章:真正的原因是选择查询的索引覆盖率很差

更改也不那么容易,因为任何消耗数据的代码都将获得相同的数据结构,而不管您将来对表模式所做的更改如何。


根据您选择所有列的说明,目前没有什么区别。但是请意识到,数据库架构确实会发生变化。如果您使用SELECT *,则将很可能将任何新列添加到表中,即使极有可能代码不准备使用或显示该新数据。这意味着您要将系统暴露于意外的性能和功能更改。

您可能愿意以较低的费用来解决此问题,但是您意识到不需要的列仍然必须是:

  • 从数据库读取
  • 通过网络发送
  • 编组到您的流程中
  • (对于ADO类型的技术)保存在内存中的数据表中
  • 忽略和丢弃/垃圾收集
  • 项#1具有许多隐藏成本,包括消除一些潜在的覆盖索引,导致数据页负载(以及服务器缓存抖动),发生行/页/表锁定,而这些锁定本来可以避免。

    在指定列和*的潜在节省之间进行权衡,唯一的潜在节省是:

  • 程序员无需重新访问SQL即可添加列
  • SQL的网络传输更小/更快
  • SQL Server查询解析/验证时间
  • SQL Server查询计划缓存
  • 对于第1项,实际情况是您将添加/更改代码以使用无论如何都可能会添加的任何新列,因此这很麻烦。

    对于第2项,差异很少会迫使您进入不同的数据包大小或数量的网络数据包。如果到了SQL语句传输时间成为主要问题的地步,则可能需要首先降低语句的速率。

    对于项目3,由于必须进行*的扩展,因此没有节省,这意味着无论如何都要查询表模式。实际上,列出列会产生相同的成本,因为必须根据架构进行验证。换句话说,这是彻底的清洗。

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

    因此,由于您指定问题的方式,面对最终的模式修改,所有这些归结为问题的弹性。如果将这种模式刻录到ROM中(发生),那么*是完全可以接受的。

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

    我的建议是,您应该始终选择特定的列。请记住,您一遍又一遍地会做得很好,所以要养成正确做事的习惯。

    如果您想知道为什么不更改代码就可以更改模式,请考虑审计日志,有效/有效日期以及DBA为系统性解决合规性问题而添加的其他类似内容。不当更改的另一个来源是系统或用户定义字段中其他地方的性能反规范化。


    您只应选择所需的列。即使您需要所有列,也最好列出列名,以便sql server不必在系统表中查询列。

    另外,如果有人向表中添加列,则您的应用程序可能会中断。您的程序将获得未曾期望的列,并且可能不知道如何处理它们。

    除此之外,如果表具有二进制列,则查询将更慢并且将使用更多的网络资源。


    select *是一件坏事的主要原因有四个:

  • 最重要的实际原因是,它迫使用户神奇地知道将返回列的顺序。最好是明确的,这也可以保护您免受表更改的影响,因为表更改可以很好地与...

  • 如果您正在使用的列名发生更改,则最好尽早(在SQL调用时)捕获它,而不是尝试使用不再存在的列(或名称已更改等)时。 )

  • 列出列名可以使您的代码更具自记录性,因此可能更具可读性。

  • 如果要通过网络传输(或者即使不是),则不需要的列也很浪费。


  • 指定列列表通常是最佳选择,因为如果有人向表中添加/插入列,您的应用程序将不会受到影响。


    为服务器指定列名绝对更快。但是如果

  • 性能并不是一个大问题(例如,这是一个网站内容数据库,每个表中有数百行,也许是数千行,但没有数百万行);和
  • 您的工作是使用通用框架创建许多小型的类似应用程序(例如,面向公众的内容管理网站),而不是创建复杂的一次性应用程序;和
  • 灵活性很重要(为每个站点定制大量的数据库模式);
  • 那么最好还是坚持使用SELECT *。在我们的框架中,SELECT *的大量使用使我们能够在表中引入一个新的网站托管内容字段,从而为它提供CMS的所有好处(版本,工作流/批准等),而只需触摸代码即可。几分,而不是几分。

    我知道数据库专家会为此而讨厌我-继续,请投下我的票-但是在我的世界中,开发人员时间紧缺,CPU周期充裕,因此我要相应地调整我所保存和浪费的东西。


    即使查询不是通过网络发送的,SELECT *也是一种不好的做法。

  • 选择比您需要的数据更多的数据会使查询效率降低-服务器必须读取和传输额外的数据,因此这会花费时间并在系统上造成不必要的负载(不仅是网络(如其他人所述,还包括磁盘,CPU等)。 )。此外,服务器无法优化查询,并且可能无法对其进行优化(例如,对查询使用覆盖索引)。
  • 一段时间后,您的表结构可能会更改,因此SELECT *将返回一组不同的列。因此,您的应用程序可能会获得意外结构的数据集并在下游某处中断。明确说明各列可确保您获得已知结构的数据集,或在数据库级别获得明确的错误(例如"未找到列")。
  • 当然,对于一个小型而简单的系统而言,所有这些都无关紧要。


    在性能方面,具有特定列的SELECT可以更快(无需读取所有数据)。如果您的查询确实确实使用了ALL列,则仍然建议使用带有显式参数的SELECT。任何速度差异基本上都是不明显的,并且接近恒定时间。有一天,您的架构将发生更改,这是防止出现此问题的良好保证。


    您实际上应该只选择所需的字段,并且仅选择所需的数字,即

    1
    SELECT Field1, Field2 FROM SomeTable WHERE --(constraints)

    在数据库之外,动态查询会带来注入攻击和数据格式错误的风险。通常,您可以使用存储过程或参数化查询来解决此问题。同样(尽管问题不大),每次执行动态查询时,服务器都必须生成一个执行计划。


    到目前为止,这里有很多充分的理由可以回答,这是另一个未提及的理由。

    明确命名列将帮助您进行后续维护。在某个时候,您将进行更改或故障排除,并发现自己在问"该列在哪里使用"。

    如果您有明确列出的名称,那么通过所有存储过程,视图等来查找对该列的每个引用都很简单。只需为您的数据库模式转储一个CREATE脚本,然后在其中搜索文本即可。


    最好指定所需的列,如果您一次考虑一下,SQL就不必在每次查询时都认为" wtf is *"。最重要的是,稍后有人可能会向查询中实际上不需要的表中添加列,在这种情况下,通过指定所有列会更好。


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

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

    不要spec测性能,不要去衡量它!

    当您有一些包含大数据的列(例如帖子或文章的正文)并且在给定查询中不需要它时,显式列表最有用。然后,通过不将其返回到答案数据库服务器中,可以节省时间,带宽和磁盘吞吐量。您的查询结果也将更小,这对任何查询缓存都非常有用。


    绝对定义列,因为SQL Server不必对列进行查询即可将其拉出。如果定义列,则SQL可以跳过该步骤。


    "选择*"的问题是可能带来不需要的数据。在实际的数据库查询期间,所选的列并没有真正添加到计算中。真正"繁重"的是将数据传输回客户端,而您真正不需要的任何列就是浪费网络带宽,并增加了等待查询返回的时间。

    即使您确实使用了" select * ..."带来的所有列,也仅此而已。如果将来您更改表/视图的布局并添加更多列,即使您不需要它们,也将开始将它们纳入选择范围。

    " select *"语句不好的另一点是在视图创建上。如果使用"选择*"创建视图,然后在表中添加列,则视图定义和返回的数据将不匹配,并且您需要重新编译视图以使它们再次起作用。

    我知道写" select *"很诱人,因为我真的不喜欢手动指定查询中的所有字段,但是当您的系统开始发展时,您会发现花额外的时间是值得的/努力指定字段,而不是花费更多的时间和精力来消除视图中的错误或优化应用程序。


    只要您的列仍然存在(以任何顺序),为您希望进入应用程序的每一列命名也可以确保如果有人更改表,您的应用程序不会中断。


    当且仅当您需要获取所有字段的数据时,使用显式字段名相对于*并不是更快。

    您的客户端软件不应该依赖于返回字段的顺序,所以这也是胡说八道。

    而且有可能(尽管不太可能)需要使用*来获取所有字段,因为您尚不知道存在哪些字段(请考虑非常动态的数据库结构)。

    使用显式字段名的另一个缺点是,如果它们很多且很长,那么会使读取代码和/或查询日志变得更加困难。

    因此,规则应为:如果需要所有字段,请使用*,如果仅需要一个子集,请明确命名它们。


    如果使用*或列,则Select同样有效(就速度而言)。

    区别在于内存,而不是速度。当您选择几列时,SQL Server必须分配内存空间来为您提供查询,包括您所请求的所有列的所有数据,即使您仅使用其中之一。

    就性能而言重要的是执行计划,而执行计划又很大程度上取决于您的WHERE子句以及JOIN,OUTER JOIN等的数量...

    对于您的问题,只需使用SELECT *。如果您需要所有列,则没有性能差异。


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

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


    与大多数问题一样,这取决于要实现的目标。如果要创建允许任何表中所有列的数据库网格,则"选择*"是答案。但是,如果您只需要某些列,并且很少在查询中添加或删除列,则分别指定它们。

    它还取决于您要从服务器传输的数据量。如果其中一列被定义为备忘录,图形,blob等,而您不需要该列,则最好不要使用"选择*",否则您将获得一大堆不需要的数据想要,您的表现可能会受到影响。


    最好明确指出所需的列的一种最佳做法是,由于表结构将来可能会发生变化。

    如果您正在使用基于索引的方法手动读取数据,以用查询结果填充数据结构,那么将来在添加/删除列时,您将很难找出问题所在。

    至于什么更快,我会请其他人提供专业知识。


    为了补充其他人所说的内容,如果您选择的所有列都包含在索引中,则将从索引中提取结果集,而不是从SQL查找其他数据。


    如果要获取元数据(例如列数),则必须使用SELECT *。


    上面每个人所说的,再加上:

    如果您正在努力寻找可读的可维护代码,请执行以下操作:

    SELECT foo,bar FROM小部件;

    立即可读并显示意图。如果您拨打该电话,您就会知道自己正在得到什么。如果小部件仅具有foo和bar列,则选择*意味着您仍然必须考虑要返回的内容,确认顺序已正确映射,依此类推。但是,如果小部件具有更多的列,但您仅对foo感兴趣和bar,那么当您查询通配符时,您的代码就会变得混乱,然后仅使用返回的一些内容。


    记住,如果定义上有内部联接,则不需要所有列,因为联接列中的数据是重复的。

    这并不像在SQl服务器中列出列那样困难甚至费时。您只需将它们从对象浏览器中拖过即可(通过从字列中拖拽可以一劳永逸)。要给您的系统带来永久性的性能下降(因为这会减少索引的使用,并且因为通过网络发送不必要的数据的开销很大),并且随着数据库的更改,您更有可能遇到意想不到的问题(有时会添加列您不希望用户看到例如)只是为了节省不到一分钟的开发时间,这是短视且不专业的。


    它取决于您的数据库服务器的版本,但是现代版本的SQL可以以任何一种方式缓存计划。我想说的是您的数据访问代码中最可维护的内容。


    如果需要每一列,则只需使用SELECT *,但请记住顺序可能会发生变化,因此当您使用结果时,请按名称而不是按索引访问它们。

    我将忽略有关*如何需要获取列表的注释-解析和验证命名列的机会等于或等于处理时间(如果不是更多的话)。不要过早优化;-)


    在执行效率方面,我不知道有什么显着差异。但是为了提高程序员的效率,我会写字段名称,因为

    • 您知道顺序,如果您需要按数字索引,或者您的驱动程序对blob值表现得很滑稽,并且需要确定的顺序
    • 如果您应该添加更多字段,则只需阅读所需的字段
    • 如果您拼写错误或重命名字段,而不是记录集/行中的空值,则会出现sql错误
    • 您可以更好地了解正在发生的事情。

    绝对定义每次要选择的列。没有理由不这样做,并且性能改进是值得的。

    他们不应该选择" SELECT *"


    还要牢记变化。今天,Select *仅选择您需要的列,但是明天它可能还会选择我刚刚添加的varbinary(MAX)列,而不会告诉您,并且您现在还检索了所有3.18 GB的二进制数据在昨天的桌子上。


    嘿,要切合实际。在原型制作时使用select *,在实现和部署时使用特定的列。从执行计划的角度来看,两者在现代系统上是相对相同的。但是,选择特定的列会限制必须从磁盘检索,存储在内存中并通过网络发送的数据量。

    最终最好的计划是选择特定的列。


    我发现列出列名特别重要,如果其他开发人员可能会使用该代码,或者数据库可能会更改,以便您始终获得一致的数据。


    效率是否重要在很大程度上取决于生产数据集的大小(及其增长率)。如果您的数据集不会那么大,并且增长不会那么快,那么选择单个列可能没有太多的性能优势。

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

    要以图形方式查看是否存在任何差异,我建议使用查询分析器查看SELECT *和等效的SELECT col1,col2等的查询执行计划。这应该告诉您两个查询中哪个效率更高。您还可以生成一些不同容量的测试数据,以了解计时时间。


    在性能方面,我已经看到了两者相同的评论。但可用性方面有一些+和-

    当您在查询中使用(选择*)时,如果有人更改了表并添加了上一个查询不需要的新字段,则这是不必要的开销。以及如果新添加的字段是Blob或image字段怎么办???那么您的查询响应时间将会非常慢。

    另一方面,如果您使用(select col1,col2,..),并且表被更改并添加了新字段,并且如果结果集中需要这些字段,则在更改表后始终需要编辑选择查询。

    但是我建议始终在查询中使用select col1,col2,...,如果表稍后更改,则更改查询。


    如果您实际上需要所有列,则SELECT *可能没问题-但您仍应单独列出所有列。您当然不应该从表中选择所有行-即使应用程序和数据库位于同一服务器或网络上。传输所有行将需要时间,尤其是随着行数的增加。您应该至少有一个where子句来过滤结果,和/或对结果进行分页以仅选择需要显示的行的子集。根据您使用的应用程序语言,有几种ORM工具可用来帮助查询和分页所需的数据子集。例如,在.NET Linq to SQL,Entity Framework和nHibernate中,所有这些都将帮助您。


    为此,我会大为震惊,但是我做了一个select *,因为几乎所有数据都是从SQL Server视图中检索的,这些视图将所需的值从多个表中预先组合到一个易于访问的视图中。

    然后,我希望视图中的所有列在将新字段添加到基础表时都不会改变。这具有使我可以更改数据来源的附加好处。可以一次计算视图中的FieldA,然后将其更改为静态。无论哪种方式,View都会向我提供FieldA。

    这样做的好处是它允许我的数据层获取数据集。然后将它们传递给我的BL,后者可以根据它们创建对象。我的主应用程序仅知道对象并与之交互。当传递数据行时,我什至允许我的对象自行创建。

    当然,我是唯一的开发人员,所以也有帮助:)


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


    对于直接查询数据库(例如在sqlplus提示符下或通过db管理工具),选择*通常就可以了-避免了写出所有列的麻烦。

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

    • 代码更清晰
    • 您将知道结果返回的顺序(这可能对您不重要)

    我总是建议指定您需要的列,以防万一您的架构发生更改并且您不需要额外的列。

    另外,用表名限定列名。当查询包含联接时,这一点至关重要。没有表资格,可能很难记住哪个列来自哪个表,并且将相似命名的列添加到其他表之一可能会破坏查询。


    对于性能而言,特别重要的是,在定义联接时至少不使用两个字段包含相同的数据时,请不要使用select *。您不想浪费网络资源,将不需要的数据从数据库服务器发送到应用程序或Web服务器。使用select *似乎更容易,但这是一个不好的做法。由于很容易将列名拖动到查询中,因此只需执行此操作即可。

    使用select *时发生的另一个问题是,有一些白痴选择在表的中间添加新字段(总是一种不好的做法),如果您使用select *作为插入的基础,那么突然您的列顺序可能是错误的做法,您可以尝试将社会安全号码插入酬金中(说话人可能会得到酬金以挑选非随机的例子),这对于数据完整性而言可能是一件非常糟糕的事情。即使选择内容不是插入内容,当数据突然按报表或网页上的破旧顺序排列时,对客户来说也很糟糕。

    我认为在使用select *时最好不要使用列列表。您可能会认为它更易于维护,但实际上并非如此,当不需要的字段添加到表中时,它会毫无理由地导致应用程序变慢。您还必须面对解决如果使用列列表就不会损坏的问题,因此,这样做节省了您不添加列的时间。


    让我们考虑哪个更快。如果您只能选择所需的数据,则速度会更快。但是,在测试中,您可以提取所有数据,以根据业务需求判断可以过滤哪些数据。


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

    • 12桌
    • 6个左联接
    • 9个内部联接
    • 所有12个表中的108个列
    • 我只需要54列
    • 4列Order By子句

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

    返回的总行数为13,949。

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


    使用特定的字段名称,因此,如果有人更改您的表,则不会得到意外的结果。关于主题:总是在插入时指定字段名称,因此,如果以后需要添加一列,则不必回头来修复程序并在生产版本中同时更改数据库。


    如果您担心速度,请确保使用准备好的语句。否则,我对ilitirit不满意,那就是您要保护自己免受变化。

    /艾伦


    两者之间的主要区别是来回传递的数据量。关于时间差的任何论点从根本上都是有缺陷的,因为" select *"和" select col1,...,colN"会导致DB引擎执行相同数量的相对工作。但是,每行传输15列对比每行传输5列是10列的差异。


    好吧,这实际上取决于您的指标和目的:

  • 如果您有250列,并且想要(确实)全部选中它们,请在当天返回家时使用select * :)
  • 如果您的编码需要灵活性并且所需的表很小,那么再次选择*可以帮助您更快地编写代码并更轻松地进行维护。
  • 如果您想要强大的工程和性能:

    • 如果列名很少,请写出它们,或者
    • 编写工具,让您轻松选择/生成列名
  • 根据经验,当我需要选择所有列时,除非有非常特殊的原因,否则我将使用" select *"(此外,我认为在包含许多列的表上速度会更快)

    最后但并非最不重要的一点是,您如何添加或删除表中的列以影响您的代码或其维护?


    在某些情况下,SELECT *可以很好地用于维护目的,但通常应避免使用。

    这些是特殊情况,例如视图或存储过程,您需要在其中传播基础表中的更改,而无需去更改使用该表的每个视图和存储过程。即使那样,它本身也会引起问题,例如在您将两个视图连接在一起的情况下。一个基础表发生了变化,现在视图变得模棱两可,因为两个表都有一个具有相同名称的列。 (请注意,这可能在您不使用表前缀限定所有列时发生)。即使具有前缀,如果您具有类似以下的构造:

    选择A.,B。-您可能会遇到客户现在难以选择正确字段的问题。

    通常,除非我做出有意识的设计决策并认为相关风险较低,否则我不会使用SELECT *。


    如果记录遍历互联网,则限制返回的列可以极大地提高性能。


    推荐阅读