哪个更快/最好? SELECT *或者SELECT column1,colum2,column3等
我听说在编写SQL命令时,通常不宜使用SELECT *,因为对我们特别需要的SELECT列更有效。
如果我需要对表中的每一列进行"选择"操作,应该使用
SELECT * FROM TABLE
或者
SELECT column1, colum2, column3, etc. FROM TABLE
在这种情况下,效率真的重要吗?我认为,如果我们确实需要所有数据,则" SELECT *"在内部会更理想,但是我说的是这并没有对数据库的真正了解。
我很好奇这种情况下的最佳做法。
更新:我可能应该指定,我真正想做一个SELECT *的唯一情况是当我从一个表中选择数据时,我知道所有列都将始终需要检索,即使添加了新列也是如此。 。
但是,鉴于我所看到的回答,这似乎仍然是一个坏主意,出于我想使用的更多技术原因,切勿使用SELECT *。
解决方案
回答
绝对定义列,因为SQL Server不必对列进行查询即可将其拉出。如果定义列,则SQL可以跳过该步骤。
回答
最好总是指定所需的列,如果我们考虑一次,SQL不必在每次查询时都认为" wtf is *"。最重要的是,稍后有人可能会向查询中实际上不需要的表中添加列,在这种情况下,通过指定所有列会更好。
回答
选择特定列更好的原因之一是,它增加了SQL Server可以从索引访问数据而不是查询表数据的可能性。
这是我写的一篇文章:真正的原因是选择查询的索引覆盖率很差
更改也不那么容易,因为任何消耗数据的代码都将获得相同的数据结构,而不管我们将来对表模式所做的更改如何。
回答
在性能方面,具有特定列的SELECT可以更快(无需读取所有数据)。如果查询确实确实使用了ALL列,则仍然建议使用带有显式参数的SELECT。任何速度差异基本上都是不明显的,并且接近恒定时间。有一天,架构将发生更改,这是防止出现此问题的良好保证。
回答
如果使用*或者列,则Select同样有效(就速度而言)。
区别在于内存,而不是速度。当我们选择几列时,SQL Server必须分配内存空间来为我们提供查询,包括我们所请求的所有列的所有数据,即使我们仅使用其中之一。
就性能而言,重要的是执行计划,而执行计划又很大程度上取决于WHERE子句以及JOIN,OUTER JOIN等的数量...
对于问题,只需使用SELECT *。如果我们需要所有列,则没有性能差异。
回答
它取决于数据库服务器的版本,但是现代版本的SQL可以以任何一种方式缓存计划。我想说的是数据访问代码中最可维护的内容。
回答
绝对定义每次要选择的列。没有理由不这样做,而且性能改进是值得的。
他们绝对不应该选择" SELECT *"
回答
如果需要每一列,则只需使用SELECT *,但请记住顺序可能会发生变化,因此在使用结果时,请按名称而不是按索引访问它们。
我将忽略有关*如何去获取列表的机会的评论,如果有更多的机会,则解析和验证命名列等于处理时间。不要过早优化;-)
回答
最好明确指出所需的列的一种最佳做法是,由于表结构将来可能会发生变化。
如果我们正在使用基于索引的方法手动读取数据,以用查询结果填充数据结构,那么将来在添加/删除列时,我们将很难尝试找出问题所在。
至于什么更快,我会尊重其他人的专业知识。
回答
在执行效率方面,我不知道有什么显着差异。但是为了提高程序员的效率,我会写字段名称,因为
- 如果需要按数字索引,或者驱动程序对blob值表现出滑稽的表情,并且需要确定的顺序,就知道顺序
- 如果我们应该添加更多字段,则只需阅读所需的字段
- 如果我们拼写错误或者重命名字段,而不是记录集/行中的空值,则会出现sql错误
- 我们可以更好地了解正在发生的事情。
回答
"选择*"的问题是可能带来不需要的数据。在实际的数据库查询期间,所选的列并没有真正添加到计算中。真正"繁重"的是将数据传输回客户端,而我们真正不需要的任何列就是浪费网络带宽,并增加了等待查询返回的时间。
即使我们确实使用了" select * ..."带来的所有列,也仅此而已。如果将来我们更改表/视图的布局并添加更多列,即使我们不需要它们,也将开始将它们纳入选择范围。
" select "语句不好的另一点是在视图创建上。如果使用"选择"创建视图,然后在表中添加列,则视图定义和返回的数据将不匹配,并且我们需要重新编译视图以使它们再次起作用。
我知道写" select *"很诱人,因为我真的不喜欢手动指定查询中的所有字段,但是当系统开始发展时,我们会发现花额外的时间是值得的/努力指定字段,而不是花费更多的时间和精力来消除视图中的错误或者优化应用程序。
回答
虽然显式列出列对性能有好处,但不要发疯。
因此,如果我们使用所有数据,为简单起见,请尝试使用SELECT *(想象有很多列并执行JOIN ...查询可能会很糟糕)。然后测量。与具有明确列出的列名的查询进行比较。
不要spec测性能,不要去衡量它!
当我们有一些包含大数据的列(例如帖子或者文章的正文)并且在给定查询中不需要它时,显式列表最有用。然后,通过不将其返回到答案数据库服务器中,可以节省时间,带宽和磁盘吞吐量。查询结果也将更小,这对任何查询缓存都非常有用。
回答
嘿,要切合实际。在原型制作时使用select *,在实现和部署时使用特定的列。从执行计划的角度来看,两者在现代系统上是相对相同的。但是,选择特定的列会限制必须从磁盘检索,存储在内存中并通过网络发送的数据量。
最终最好的计划是选择特定的列。
回答
指定列列表通常是最好的选择,因为如果有人向表中添加/插入列,应用程序将不会受到影响。
回答
还要牢记变化。今天,Select *仅选择我们需要的列,但是明天它可能还会选择我刚刚添加的varbinary(MAX)列,而不会告诉我们,现在我们还可以获取所有3.18 GB的二进制数据在昨天的桌子上。
回答
让我们考虑哪个更快。如果我们只能选择所需的数据,则速度会更快。但是,在测试中,我们可以提取所有数据,以根据业务需求判断可以过滤掉哪些数据。
回答
如果记录遍历互联网,则限制返回的列可以极大地提高性能。
回答
当且仅当我们需要获取所有字段的数据时,使用显式字段名相对于*并不是更快。
客户端软件不应该依赖于返回字段的顺序,所以这也是胡说八道。
而且有可能(尽管不太可能)需要使用*来获取所有字段,因为我们尚不知道存在哪些字段(请考虑非常动态的数据库结构)。
使用显式字段名称的另一个缺点是,如果它们很多且很长,那么会使读取代码和/或者查询日志变得更加困难。
因此,规则应为:如果需要所有字段,请使用*,如果仅需要一个子集,请明确命名它们。
回答
好吧,这实际上取决于指标和目的:
- 如果我们有250列,并且想要(确实)全部选择它们,请在当天返回家时使用select * :)
- 如果编码需要灵活性,并且所需的表很小,那么再次选择*可以更快地编码并更轻松地进行编码。
- 编写工具,让我们轻松选择/生成列名
根据经验,当我需要选择所有列时,除非有非常特殊的原因,否则我将使用" select *"(此外,我认为在包含许多列的表上速度更快)
最后但并非最不重要的一点是,我们如何添加或者删除表中的列以影响代码或者其维护?
回答
与大多数问题一样,这取决于我们要实现的目标。如果要创建允许任何表中所有列的数据库网格,则"选择*"是答案。但是,如果我们只需要某些列,并且很少在查询中添加或者删除列,则分别指定它们。
它还取决于我们要从服务器传输的数据量。如果其中一列定义为备忘录,图形,blob等,而我们不需要该列,则最好不要使用"选择*",否则我们将获得一大堆不需要的数据想要,表现可能会受到影响。
回答
两者之间的主要区别在于来回传递的数据量。关于时间差的任何论点从根本上都是有缺陷的,因为" select *"和" select col1,...,colN"会导致DB引擎执行相同数量的相对工作。但是,每行传输15列对比每行传输5列是10列的差异。
回答
如果我们担心速度,请确保使用准备好的语句。否则,我不满于改变,这就是我们保护自己免受攻击的地方。
/艾伦
回答
我总是建议我们指定所需的列,以防万一架构发生更改并且我们不需要多余的列。
另外,用表名限定列名。当查询包含联接时,这是至关重要的。如果没有表资格,可能很难记住哪个列来自哪个表,并且将相似命名的列添加到其他表之一可能会中断查询。
回答
使用特定的字段名称,因此,如果有人更改了表,则不会得到意外的结果。关于主题:总是在插入时指定字段名称,因此,如果以后需要添加一列,则不必回头修复程序并在生产版本中同时更改数据库。
回答
我发现列出列名特别重要,如果其他开发人员可能会使用该代码,或者数据库可能会更改,以便我们始终获得一致的数据。
回答
效率是否重要在很大程度上取决于生产数据集的大小(及其增长率)。如果数据集不会那么大,并且增长不会那么快,那么选择单个列可能没有太多的性能优势。
随着更大的数据集和更快的数据增长速度,性能优势变得越来越重要。
要以图形方式查看是否存在任何差异,我建议使用查询分析器查看SELECT *和等效的SELECT col1,col2等的查询执行计划。这应该告诉我们两个查询中哪个效率更高。我们还可以生成一些不同容量的测试数据,以了解计时时间。
回答
要补充其他人所说的话,如果我们选择的所有列都包含在索引中,则将从索引中提取结果集,而不是从SQL查找其他数据。
回答
根据我们选择所有列的说明,目前没有什么区别。但是请意识到,数据库架构确实会发生变化。如果我们使用SELECT *,我们将获得添加到表中的任何新列,即使代码很可能不准备使用或者展示该新数据。这意味着我们要将系统暴露于意外的性能和功能更改。
我们可能愿意以较低的费用来解决此问题,但是我们意识到不需要的列仍然必须是:
- 从数据库读取
- 通过网络发送
- 编组到流程中
- (对于ADO类型的技术)保存在内存中的数据表中
- 忽略和丢弃/垃圾收集
项#1具有许多隐藏成本,包括消除一些潜在的覆盖索引,导致数据页负载(以及服务器缓存抖动),发生行/页/表锁定,而这些锁定本来可以避免。
将这与指定列相对于*的潜在节省进行权衡,唯一的潜在节省为:
- 程序员无需重新访问SQL即可添加列
- SQL的网络传输更小/更快
- SQL Server查询解析/验证时间
- SQL Server查询计划缓存
对于第1项,实际情况是我们将添加/更改代码以使用无论如何都可能会添加的任何新列,因此这很麻烦。
对于第2项,差异很少会迫使我们进入不同的数据包大小或者数量的网络数据包。如果到了SQL语句传输时间成为主要问题的地步,则可能需要首先降低语句的速率。
对于第3项,没有节省,因为无论如何都必须扩展*,这意味着无论如何都要查询表模式。实际上,列出列会产生相同的成本,因为必须根据架构进行验证。换句话说,这是彻底的清洗。
对于项目4,当我们指定特定的列时,查询计划缓存可能会变大,但前提是我们要处理不同的列集(这不是我们指定的内容)。在这种情况下,我们确实需要不同的缓存条目,因为我们需要根据需要使用不同的计划。
因此,由于我们指定问题的方式,面对最终的模式修改,所有这些归结为问题的弹性。如果将这种模式刻录到ROM中(发生),那么*是可以接受的。
但是,我的一般指导原则是只应选择所需的列,这意味着有时看起来像我们要所有这些列,但是DBA和模式演变意味着可能会出现一些新列,这些列会极大地影响查询。
我的建议是,我们应该始终选择特定的列。请记住,我们一遍又一遍地会做得很好,所以要养成正确做事的习惯。
如果我们想知道为什么不更改代码就可以更改模式,请考虑审核日志记录,有效/到期日期以及DBA为系统性合规性问题而添加的其他类似内容。欠妥之处的另一个来源是系统或者用户定义字段中其他地方的性能反规范化。
回答
对于性能而言,特别重要的一点是,在定义联接时至少不使用两个字段包含相同的数据时,请不要使用select *。我们不想浪费网络资源将不需要的数据从数据库服务器发送到应用程序或者Web服务器。使用select *似乎更容易,但这是一个坏习惯。由于很容易将列名拖动到查询中,因此只需执行此操作即可。
使用select *时发生的另一个问题是,有一些白痴选择在表的中间添加新字段(总是一种不好的做法),如果我们使用select *作为插入的基础,那么列顺序可能突然变成了错误的做法,我们可能会尝试将社会安全号码插入酬金中(说话人可能会得到酬金以挑选非随机的例子),这对于数据完整性而言可能是一件非常糟糕的事情。即使选择内容不是插入内容,当数据突然按报表或者网页上的破旧顺序排列时,对客户来说也很糟糕。
我认为在使用select *时最好不要使用列列表。我们可能会认为它更易于维护,但实际上并非如此,当我们将不需要的字段添加到表中时,它会毫无理由地导致应用程序变慢。我们还必须面对修复如果使用列列表就不会损坏的问题,因此,这样做节省了我们不添加列的时间。
回答
在某些情况下,SELECT *可以很好地用于维护目的,但通常应避免使用它。
这些是特殊情况,例如视图或者存储过程,我们希望在其中传播基础表中的更改,而无需去更改使用该表的每个视图和存储过程。即使这样,这本身也会引起问题,例如在我们将两个视图连接在一起的情况下。一个基础表发生了变化,现在视图变得模棱两可了,因为两个表都有一个具有相同名称的列。 (请注意,如果我们不使用表格前缀来限定所有列,则可能会发生这种情况)。即使带有前缀,如果我们具有类似以下的构造:
选择A,B。我们现在可能遇到客户无法选择正确字段的问题。
通常,除非我做出有意识的设计决策并认为相关风险较低,否则我不会使用SELECT *。
回答
对于直接查询数据库(例如,在sqlplus提示符下或者通过数据库管理工具),选择*通常就可以了-避免了写出所有列的麻烦。
另一方面,在应用程序代码中,最好枚举列。这有几个好处:
- 代码更清晰
- 我们将知道结果返回的顺序(这可能对我们不重要)
回答
为服务器指定列名绝对更快。但是如果
- 性能并不是一个大问题(例如,这是一个网站内容数据库,每个表中有数百行,也许是数千行,但没有数百万行);和
- 工作是使用通用框架创建许多小型的类似应用程序(例如,面向公众的内容管理网站),而不是创建复杂的一次性应用程序;和
- 灵活性很重要(为每个站点定制大量的数据库模式);
那么最好还是坚持使用SELECT *。在我们的框架中,SELECT *的大量使用使我们可以在表中引入一个新的网站托管内容字段,从而为它提供CMS的所有好处(版本,工作流/批准等),而只需触摸代码即可。几分,而不是几十分。
我知道数据库专家会为此而讨厌我,请投票否决,但是在我的世界中,开发人员时间紧缺,CPU周期充裕,因此我要相应地调整我所节省和浪费的东西。
回答
如果要获取元数据(例如列数),则必须使用SELECT *。
回答
我看到有些人似乎认为指定列花费的时间更长。由于可以从对象浏览器中拖动列列表,因此在查询中指定列可能要花费额外的时间(也就是说,如果我们有很多列并且需要花费一些时间将它们放在单独的行上)。人们为什么认为这是如此耗时?
回答
为此,我会大为吃惊,但我做了一个select *,因为几乎所有数据都是从SQL Server视图中检索的,这些视图将所需的值从多个表中预先组合到一个易于访问的视图中。
然后,我希望视图中的所有列在将新字段添加到基础表时都不会改变。这具有使我可以更改数据来源的添加好处。可以一次计算视图中的FieldA,然后将其更改为静态。无论哪种方式,View都会向我提供FieldA。
这样做的好处是它允许我的数据层获取数据集。然后将它们传递给我的BL,后者可以根据它们创建对象。我的主应用程序仅知道对象并与之交互。当传递数据行时,我什至允许我的对象自行创建。
当然,我是唯一的开发人员,所以也有帮助:)
回答
结果太大。生成结果并将结果从SQL引擎发送到客户端的速度很慢。
客户端不是通用编程环境,因此也不应该设计用于过滤和处理结果(例如WHERE子句,ORDER子句),因为行数可能很大(例如数千万行)。
回答
我们只应选择所需的列。即使我们需要所有列,也最好列出列名,以便sql server不必在系统表中查询列。
另外,如果有人向表中添加列,则应用程序可能会中断。程序将获得未曾期望的列,并且可能不知道如何处理它们。
除此之外,如果表具有二进制列,则查询将更慢并且将使用更多的网络资源。
回答
我们实际上应该只选择所需的字段,并且仅选择所需的数字,即
SELECT Field1, Field2 FROM SomeTable WHERE --(constraints)
在数据库外部,动态查询会带来注入攻击和数据格式错误的风险。通常,我们可以使用存储过程或者参数化查询来解决此问题。同样(尽管问题不大),每次执行动态查询时,服务器都必须生成一个执行计划。
回答
如果我们确实需要所有列,则可以使用SELECT *,但仍应单独列出所有列。即使应用程序和数据库位于同一服务器或者网络上,我们当然也不应该从表中选择所有行。转移所有行将需要时间,尤其是随着行数的增加。我们应该至少有一个where子句来过滤结果,和/或者对结果进行分页以仅选择需要显示的行的子集。根据我们使用的应用程序语言,有几种ORM工具可用来帮助查询和分页所需的数据子集。例如,在.NET Linq to SQL,Entity Framework和nHibernate中,所有这些都将。
回答
只要列仍然存在(以任何顺序),为我们希望进入应用程序的每一列命名也可以确保如果有人更改表,应用程序不会中断。
回答
即使查询不是通过网络发送的,SELECT *也是一种不好的做法。
- 选择比我们需要的数据更多的数据会使查询效率降低-服务器必须读取和传输额外的数据,因此这会花费时间并在系统上造成不必要的负载(不仅是网络(如其他人所述,而且还包括磁盘,CPU等)。 )。此外,服务器无法优化查询,并且可能无法对其进行优化(例如,对查询使用覆盖索引)。
- 一段时间后,表结构可能会更改,因此SELECT *将返回一组不同的列。因此,应用程序可能会获得意外结构的数据集,并在下游某处中断。明确说明各列可确保我们获得已知结构的数据集,或者在数据库级别获得明确的错误(例如"未找到列")。
当然,对于一个小型而简单的系统而言,所有这些都无关紧要。
回答
"选择*"是一件坏事有四个大原因:
- 最重要的实际原因是,它迫使用户神奇地知道将返回列的顺序。最好是明确的,这也可以保护我们免受表更改的影响,因为表更改可以很好地适合于...
- 如果我们正在使用的列名称发生更改,则最好尽早(在SQL调用时)捕获它,而不是在尝试使用不再存在(或者名称已更改等)的列时。 )
- 列出列名可以使代码更具自记录性,因此可能更具可读性。
- 如果要通过网络传输(或者即使不是),则不需要的列也很浪费。
回答
以上每个人都说了,再加上:
如果我们正在努力寻找可读的可维护代码,请执行以下操作:
SELECT foo,bar FROM小部件;
立即可读并显示意图。如果我们拨打该电话,我们就会知道自己正在得到什么。如果窗口小部件仅具有foo和bar列,则选择*意味着我们仍然必须考虑要返回的内容,确认顺序已正确映射,依此类推。但是,如果窗口小部件具有更多列,但我们只对foo和bar,那么当我们查询通配符,然后仅使用返回的内容时,代码会变得混乱。
回答
并记住,如果按照定义具有内部联接,则不需要所有列,因为联接列中的数据是重复的。
这并不像在SQl服务器中列出列那样困难甚至费时。我们只需将它们从对象浏览器中拖过来即可(通过从字列中拖拽可以一劳永逸)。要给系统带来永久性的性能下降(因为这会减少索引的使用,并且因为通过网络发送不需要的数据的开销很大),并且随着数据库的更改,我们更有可能遇到意想不到的问题(有时会添加列我们不希望用户看到例如)只是为了节省不到一分钟的开发时间,这是短视和不专业的。
回答
到目前为止,这里有很多充分的理由可以回答,这是另一个没有被提及的理由。
明确命名列将进行后续维护。在某个时候,我们将进行更改或者故障排除,并发现自己在问"该列在何处使用"。
如果我们有明确列出的名称,那么通过所有存储过程,视图等来查找对该列的每个引用都很简单。只需为数据库模式转储一个CREATE脚本,然后在其中搜索文本即可。