返回的列数是否会影响查询的速度?

时间:2009-05-12 12:43:38

标签: sql performance

如果我有两个问题

SELECT Id, Forename, Surname
FROM Person
WHERE PersonName Like(‘%frank%’)

SELECT *
FROM Person
WHERE PersonName Like(‘%frank%’)

哪个查询运行得更快? where子句/表是加入最大因子还是返回的列数?

我问,因为我正在构建一系列映射到数据库表的对象。通常,每个对象至少具有以下三种方法:

Select - 选择所有内容

List - 选择足够的可用于填充下拉列表

Search - 选择结果中可见的所有内容,通常约为6列。

如果每个查询返回完全相同的列集,则代码的维护和测试应该更加简单。在任何给定的表中,数据库不可能超过50,000行,因此如果性能差异很小,那么我将节省开发时间。如果表演会在场上摔倒,那么我将从不同的角度来处理。

因此,为了便于开发,SELECT *是明智的,还是天真的?

18 个答案:

答案 0 :(得分:25)

最好避免SELECT *

  • 更改表格布局时会导致混淆。
  • 选择不需要的列,您的数据包会变大。
  • 列可能会出现重复的名称,这对某些应用程序也不利
  • 如果索引涵盖了您需要的所有列,SELECT columns将仅使用此索引,而SELECT *将需要访问表记录以获取您不需要的值。对性能也不利。

答案 1 :(得分:7)

SELECT *通常不是一个好主意。它可能不会减慢您的DBMS获取速度,但它可能会导致通过网络传输的数据超出您的需要。

然而,通过使用基本上不可索引的LIKE '%frank%'子句,这很可能会被淹没,并且会导致全表扫描。

您可能需要考虑在数据进入数据库时​​清理数据,因为这几乎肯定会使后续查询运行得更快。

如果你是坦率的,那么确保它存储为坦诚并使用:

select x,y,z from table where name = 'frank'

如果你想获得富兰克林,请使用:

select x,y,z from table where name like 'frank%'

这两个都可以在名称列上使用索引,而"%frank%"则不会。

答案 2 :(得分:5)

我要反对这里的流程并说你应该选择*。我认为过早优化是许多问题的根源,您可能会发现它在您实际使用时不会影响您的性能。当然,通过这本书,它必须更慢,但这并不意味着差异在实践中很重要。

但是,需要注意的是,某些SQL引擎(肯定是MS-SQL)会缓存select *,因此如果您使用的是预准备语句,或者是使用它的视图或存储过程,那么表模式,除非重新编译视图或sp,否则它不会接收更改,因此如果您没有动态运行这些查询,这是避免这样做的一个很好的理由。

当然,这因数据库引擎而异,因此需要进行一些负载测试,以确保命中率不会很大。

答案 3 :(得分:2)

对于小型项目,您通常可以使用select *。不过,这样做是“正确的”。对于非索引查询中的一个表,您不会注意到任何明显的速度差异...您唯一明显的做法是为未读取的列使用更多带宽。

也就是说,当你只需要点击索引时,你会注意到只有索引的查询才能达到完整的表格。当你正在加入时,这尤其会突然出现。

Select *确实有用,如果你正确使用它(比如,结合缓存,确保它是select table.*,并按列名寻址结果)你可以减少由你的申请。

答案 4 :(得分:2)

无论性能如何,最好始终枚举查询中的所有字段。

  • 如果您决定在将来添加用于特定查询的TEXT或BLOB列,该怎么办?无论您是否需要,您的SELECT *都将返回其他数据。
  • 如果重命名列怎么办?您的SELECT *将始终有效,但依赖代码将被破坏。

答案 5 :(得分:1)

如果从大学中正确记得(并且已经有一段时间了),选择*不是首选,但不是那么糟糕 - 直到你开始加入。当你进入创建连接元组的关系模式时,每一列都会增加时间,所以如果可能的话我肯定会避免它。

答案 6 :(得分:1)

表中的列数不会影响查询的性能。在查询中操作的列数将为。

请注意Oracle概念手册中的以下示例:

  

行格式和大小Oracle存储每个   包含的数据库表的行   少于256列的数据为一   或更多的行件。如果整行   可以插入单个数据中   阻止,然后Oracle将该行存储为   一排。但是,如果所有的   行的数据无法插入到   单个数据块或更新   现有行会导致行   超过它的数据块,然后是Oracle   使用多行存储行   件。数据块通常包含   每行只有一个行块。什么时候   Oracle必须存储多行   一排,它被链接   多个街区。

     

表格超过255时   列,后面有数据的行   第255列很可能被链接   在同一个街区内。这就是所谓的   块内链接。一个链式的行   使用的链接件连在一起   这些碎片。内部块   链接,用户收到所有数据   在同一个街区。如果行符合   块,用户看不到效果   在I / O性能方面,因为没有额外的   检索需要I / O操作   其余部分。

     

但是:如果有400列,我   会打赌大多数行都不合适   在一个街区,因此你会看到一个   更多'db file sequential read'   比通常要求的。我也是   记住史蒂夫亚当斯(或某人   很久以前)提到有一个   访问列的额外费用   “在列表的下方” - 抱歉不要   有那个链接。

答案 7 :(得分:0)

这有多个方面。一旦*将使您的代码更脆弱。在更高版本中,您更改表格布局依赖于列顺序的代码可能会中断 - 或者可能不会读取或修改错误的列,如果数据类型仍然匹配,这可能是一个非常讨厌的问题!

此外,如果您始终请求所有列,则需要在数据库客户端和数据库服务器上为不需要的列提供更多内存。如果表包含长字符字段,非常多字段和/或BLOB,则这可能非常昂贵。选择不必要的列也会使服务器的缓存淹没在客户端从未查看过的超级内容中。

所以一般来说你不应该使用它。大多数对象关系映射工具生成包含所有列名的SQL,因此在开发过程中这可能不是问题。我个人只倾向于使用*来进行快速的即席查询,我必须手动输入。

答案 8 :(得分:0)

让我扮演恶魔倡导者,并建议一个SELECT *是更好的选择的场景。假设您正在创建一个用户界面,您可以在其中获取数据集的结果并以某种形式的表格或网格显示它。您可以在UI中构建列以匹配数据集中的列,并执行SELECT * FROM MyView。

通过在数据库中使用View,您可以完全控制查询返回的列,并且UI可以足够动态地显示所有列。对视图的更改将立即反映在UI中而不重新编译和re0显然我建议遵循先前的建议并指定视图定义中的所有列。

只是想我会补充一点,因为有时候人们会因为遵循某些规则而忘记这种情况而烦恼。

答案 9 :(得分:0)

SELECT *会慢一些,因为它必须传输更多数据。还因为已经提到的一些其他原因。加入表格时确实会出现问题,因为您开始添加更多列,而实际上您只想加入以便进行过滤。

如果你真的想使用*,请指定你想要所有列的表,比如SELECT Person。* FROM Person ...

这将缩小返回的数据量并使其更具可读性。

答案 10 :(得分:0)

我使用“select *”的唯一时间不是真正的“select *”事件

具体是:

select count(*) from table

不同

select count(ID) from table

第一个返回表中的行数 但第二个返回带有NOT NULL ID值的行数。

一种微妙的区别,但值得记住。

答案 11 :(得分:0)

这是正确的方法,也是最优的。原因是您只收集所需的数据,因此在获得结果之前,它会占用正确的空间(您需要的)存储数据。

SELECT Id, Forename, Surname
FROM Person
WHERE PersonName Like(‘%frank%’)

这是不正确的,因为它会占用未使用的字段,这会占用更多空间来运行查询,从而降低了搜索结果的速度。即使您很幸运并使用查询中的所有字段,最好单独列出它们。这将澄清查询以及将哪些数据返回给可能需要在将来修改查询的任何其他开发人员。

SELECT *
FROM Person
WHERE PersonName Like(‘%frank%’)

答案 12 :(得分:0)

除了其他答案之外,请考虑SELECT *将返回查询中所有表的数据。通过JOIN开始添加其他表,您将开始看到您不想看到的内容。

我相信我也看到过SELECT *需要实际从连接表中获取数据的情况,而不是只使用该表上的索引来帮助缩小整个结果集。不过,我想不出一个例子。

答案 13 :(得分:0)

是的。基本上是:

  • 必须从数据库服务器传输更多数据
  • 数据库服务器必须获取更多数据

您不应该使用select *

答案 14 :(得分:0)

通常,在任何情况下,您都希望远离使用

SELECT * FROM TABLE
你的代码中的

。这样做可能会导致一些问题,其中只有一个是性能问题。我能想到的另外两个问题是资源利用率(如果您选择了不需要的列,或者有人稍后添加了列...您将带回数据并浪费内存)和代码可读性(如果有人在您的代码中看到SELECT * FROM ...他们不一定知道您的应用程序中实际使用了哪些列。

只需考虑几件事......但最佳做法是不要使用它。

答案 15 :(得分:0)

我会访问此question,了解为什么不首选使用“Select *”构造。

根据我的经验,在3列表中选择3列与select *可能没有明显的影响性能,但随着表格越来越大,你会注意到性能差异。

答案 16 :(得分:0)

如果此人只有Id,Forename和Surname,则查询应该是等效的。但是,查询时间将与返回的列数(实际数据量)成比例增长。

此外,如果查询只需要这三列,您应该只询问这三列。如果您选择SELECT *并且稍后更改了架构,那么基本上只是为所有查询添加额外的处理而没有真正的额外好处。

答案 17 :(得分:-2)

不确定。更好地命名要检索的列。