我听说SELECT *
在编写SQL命令时使用通常是不好的做法,因为它对SELECT
您特别需要的列更有效.
如果我需要SELECT
表中的每一列,我应该使用
SELECT * FROM TABLE
要么
SELECT column1, colum2, column3, etc. FROM TABLE
在这种情况下,效率真的重要吗?SELECT *
如果你确实需要所有的数据,我认为内部会更优化,但我说的是没有真正了解数据库.
我很想知道在这种情况下最佳做法是什么.
更新:我可能应该指定我真正想要做的唯一情况SELECT *
是当我从一个表中选择数据时我知道所有列总是需要被检索,即使添加了新列.
鉴于我所看到的反应,这仍然是一个坏主意,SELECT *
永远不应该用于更多技术原因,我曾经考虑过.
选择特定列的更好的一个原因是它提高了SQL Server可以从索引访问数据而不是查询表数据的可能性.
这是我写的关于它的帖子: 选择查询的真正原因是索引覆盖率差
它的变化也不那么脆弱,因为任何使用数据的代码都将获得相同的数据结构,而不管您将来对表模式所做的更改.
鉴于你的规范,你是选择所有列,几乎没有什么差别 此时.但是,要意识到数据库模式确实会发生变化.如果您使用,SELECT *
您将获得添加到表中的任何新列,即使很可能,您的代码也不准备使用或显示该新数据.这意味着您将系统暴露给意外的性能和功能更改.
您可能愿意将此视为次要成本,但要意识到您不需要的列仍必须是:
从数据库中读取
通过网络发送
编入你的过程
(对于ADO类型的技术)保存在内存中的数据表中
忽略并丢弃/垃圾收集
项目#1有许多隐藏成本,包括消除一些潜在的覆盖索引,导致数据页面加载(以及服务器缓存颠簸),导致可能以其他方式避免的行/页面/表锁定.
将此与指定列与a *
的潜在节省相平衡,唯一可能的节省是:
程序员不需要重新访问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*将返回一组不同的列.因此,您的应用程序可能会获得意外结构的数据集并在下游的某处中断.明确说明列可确保您获得已知结构的数据集,或者在数据库级别上获得明确的错误(例如"未找到列").
当然,对于一个小而简单的系统来说,这一切并不重要.