使用SELECT *时的性能问题?

时间:2009-01-28 13:16:35

标签: sql database performance

  

可能重复:
  Which is faster/best? SELECT * or SELECT column1, colum2, column3, etc
  What is the reason not to use select *?

使用SELECT *而不是SELECT FiledName,FiledName2 ......?

是否存在任何性能问题

19 个答案:

答案 0 :(得分:11)

答案 1 :(得分:8)

如果你需要列的一个子集,你就会给优化器提供不好的帮助(不能选择索引,或者不能只搜索索引,......)

某些数据库可以选择仅从索引中检索数据。那件事非常有帮助,并给出了令人难以置信的加速。运行SELECT *查询不允许这个技巧。

无论如何,从申请的角度来看并不是一个好习惯。


示例:

  • 你有一张包含20列的表T(C1,C2,...,C19 C20)。
  • 你有一个关于(C1,C2)
  • 的T的索引
  • 您制作SELECT C1, C2 FROM T WHERE C1=123
  • 优化器拥有索引的所有信息,不需要转到表Data

相反,如果您SELECT * FROM T WHERE C1=123,优化器需要获取所有列数据,则不能使用(C1,C2)上的索引。

在多个表的连接中有很多帮助。

答案 2 :(得分:5)

每次执行select *时, 可能是获取列列表的附加查询。在高事务环境中,这个可以成为一个可见的开销,但是偶尔会有一次没有区别。

此外,在插入记录时,如果添加了列,请不要在插入中使用select *。

答案 3 :(得分:3)

唯一的性能问题是,如果您的应用程序只需要select *返回的字段的子集。数据库没有性能差异,因为它们实际上是相同的。

答案 4 :(得分:2)

我不了解计算性能,但就读取/维护能力(即人性能)而言,我们不在商店使用select *。一切都是明确选择的。

答案 5 :(得分:2)

我不是DBA,但从我记得从DBA学到的东西,推理(至少对SQL Server)是DB缓存算法不能很好地缓存'*'查询,但如果你正在运行具有多次指定的精确列的相同查询,它将缓存得很好。

我确信知识渊博的DBA可以详细了解缓存机制的工作原理,但这就是性能受损的原因。

注意:缓存性能仅在查询要多次运行时才有效,特别是在较短的时间范围内,否则您将看不到性能差异。

答案 6 :(得分:2)

也许。它在很大程度上取决于数据库引擎,它如何存储东西,返回的行数,有多少其他列以及其他列的大小。

如果你正在使用一个基于行的数据库(即大部分数据库)将所有列存储在一起(几乎所有列都存在,除了BLOB经常单独存储,特别是较大的那些),那么SELECT *几乎没有对服务器本身的影响 - 无论如何都必须获取整个行。

另一方面,如果您通过网络发送数据(或者甚至是本地发送数据,因为它会影响所使用的缓冲区的大小等),那么可能会有更少的列,因为会有更少的列要发回的字节数。如果查询以任何方式困难(例如需要IO),那么服务器性能无论如何都会使这种差异相形见绌。

如果行中有大blob,SELECT *不是很聪明 - 否则,它不太可能有太大的区别,但可以。

有一些“基于列”的数据库引擎敲响了 - 它们完全不同 - 对于它们来说,“SELECT *”是一个完整的性能杀手;一定要避免它。很有可能,如果您使用的话,您完全了解这一点(通常它们用于非常大的数据仓库应用程序)。

对我来说,不使用“SELECT *”的主要优点是可维护性。当有人在表中添加额外的列时,您不会感到惊讶;当有人删除您正在使用的其中一列时,您的查询“会快速失败”。它使代码更加自我记录,因为有人可以随便看看你想要的列。

答案 7 :(得分:1)

如果指定了所有字段,那么不,在性能方面不应该存在有意义的差异。但是如果你只想要一个包含十几列的表中的几个特定字段,那就慢了。

SELECT *存在可读性和可维护性问题。即使您想要选择所有字段,也始终使用特定字段名称是有意义的。

答案 8 :(得分:1)

表现,并不多。它只是有点笨拙:在一个表中,比如说,有10列,连接另外两个表甚至更多,特别是对于大型结果集,SELECT *可以返回几十列,通常是大多数未使用或甚至无用的数据。就DBMS的命中而言,不会有太多,但所有数据仍然需要以某种方式穿过线路;网络带宽和随之而来的延迟肯定会增加。我在高容量环境中亲眼目睹了这一点。这绝对重要。

除了带宽问题之外,您还可能遇到模糊的列命名问题(消除歧义通常意味着无论如何都要删除SELECT *,因此您可能从一开始就这样做),并且它也被认为是明确的良好做法代码内部代码的需求;这样做有很多方面的帮助 - 通过调试,协作等等。

答案 9 :(得分:1)

如果在连接中使用select *,则会自动发送超出您需要的信息,因为重复了连接字段。这会浪费处理时间和网络资源,并可能导致性能问题。进一步不指定字段意味着您的应用程序在添加新字段时可能会中断,特别是如果它们是用户不打算查看但是用于审计或数据库类型处理的字段。在插入中选择*总是一个坏主意,因为某些地方的某些人可能实际上改变了表格中列的顺序。

答案 10 :(得分:0)

SELECT *在运行之前被转换为SELECT Field1,Field2 ....等,因此它们实际上是相同的。没有性能差异。

然而,当SELECT Field1,Field2 ..

时,可读性和可维护性更好

答案 11 :(得分:0)

从技术上讲,它取决于您使用的关系数据库管理系统。我认为性能打击将是微秒。如果你绝对试图从系统中挤出最后一点性能,我会说不要使用它们。

我个人经常使用它。

答案 12 :(得分:0)

据说是的。我在工作中全心全意地告诉我,我永远不应该使用SELECT *。实际上,我们的策略是不使用它,因为a)这意味着通过查看查询而使用的内容和可用的内容存在歧义,b)由于SQL服务器必须找到所需的每个列并返回它们,因此速度较慢

但是,我从未见过这方面的证据。

编辑:此外,如果在服务器上编译存储过程并使用SELECT *,则当基础表结构更改所谓的时,它将不会选择新的引入列,因为SQL将SELECT *编译为单个列。

答案 13 :(得分:0)

如果您只使用字段的子集,那么性能差异可能很大。请参阅以下示例,其中涉及从CScoutanalysis of the Linux code检索1,411,771行。

$ time sh -c "echo 'select * from IDS' | mysql cslinux >/dev/null"
real    0m5.622s
user    0m2.580s
sys     0m0.532s

$ time sh -c "echo 'select EID from IDS' | mysql cslinux >/dev/null"
real    0m4.492s
user    0m0.716s
sys     0m0.096s

这甚至不能衡量对服务器的性能影响。

答案 14 :(得分:0)

如果您在代码中嵌入sql,那么为了清晰起见,您应该始终使用长格式,而不是性能。对于即席查询,select *语法基本上不比指定列名有效,除非你有大量的列,除非你进行非规范化,否则你不应该这样做。

我应该在一个句子中使用2个unlesses获得1分并且仍然坚持它是有意义的! :)

答案 15 :(得分:0)

SELECT *要求SQL查找所有列名称,但这不是远程攻击中最大的性能。

SELECT *语句的最大性能影响是当您执行需要非聚集索引进行评估的查询时。即使非聚簇索引是每列的覆盖索引,SQL仍将查找主键并从聚簇索引中获取值。

除此之外,如果您只需要一列或两列,则由于返回的结果集大于要求而导致网络瓶颈处理。

答案 16 :(得分:0)

我将回应其他人所说的“select *”检索列表列表作为请求处理的一部分。相比之下,您还可以按顺序选择列,这样可以节省更多时间,因为RDBMS引擎甚至不需要查找列来确定要检索的列的位置。我觉得这对聚合查询非常有用。

例如:从...中选择count(1)与从...中选择计数(*)

在这个例子中,RDBMS只需要知道它需要第一列的计数,而ZING,它是关闭的。在(不幸的)更常见的选择计数(*)中,RDBMS检索所有列的列表,然后验证每一行以确定它是否对计数有效(而不是仅验证第1列)。

这在大多数情况下都很有效。我很确定大多数数据库系统在计数中都会计算NULL值,但是你应该注意这一点并在假设之前进行验证。

YMMV,在禁止的地方无效等等!

答案 17 :(得分:0)

<强>性能 如果您不需要所有列,这将始终是坏的。返回的数据超过了所需数据,这将限制数据库和LAN / wan带宽。

<强>可读性 知道视图中的哪些列,过程可能非常有用,SELECT *根本没用,我认为它适得其反。

<强> *测试 如果您进行架构更改,那么在中使用SELECT *的所有代码都应该无效,因为您为检查元数据而编写的任何测试都应该检查视图proc的输出。

*当然,假设您已经完成了测试,因为所有优秀的DB Dev应该具备:)

答案 18 :(得分:0)

我同意除了某些表现声明之外的所有答案。如果你实际上要使用表中的所有列,我认为SELECT *版本更快。原因如下:

在(id,x)上有唯一索引的表上进行这两个查询:

SELECT x,y,z,w FROM tab WHERE id='abc' ORDER BY s

SELECT x,y,z,w FROM tab WHERE id='abc' 
AND x in ('a','b','c','d','e','f','g','h',...)
ORDER BY ('a','b','c','d','e','f','g','h',...)

哪个更快?如果'x in'子句在id'abc'的表中为x的所有值命名,那么第一个查询可能更快。现在让我们重命名这些字段:

SELECT field_name, field_type, field_offset, field_len
FROM internal_field_catalog
WHERE table_name = 'abc'
ORDER BY field_order

因此,在检索数据时,SELECT *允许引擎执行(相当于)单个memcpy以将行数据移动到结果集,并且在检索字段数据时可能更快地选择它。

我只是说有一个边缘情况,SELECT *非常有用,可能更快。您可能始终需要表中所有列的一个原因是在RDBMS中存储对象持久性(由于某种原因)。每个经验法则都有例外。