2010-10-05 23 views
3

为了序言,我知道(应该如此!)在生产中使用SELECT *是不好的,但我维护着其他人编写的脚本。而且,我也意识到这个问题在具体情况上很低......但是假设的情况。假设的性能良率不使用SELECT *

比方说,我有一个脚本,从20个字段的表中选择一切。让我们说典型的客户信息。

然后让我们说,作为一名优秀的开发人员,我将SELECT *缩短为实际使用的13个特定字段中的SELECT

通过明确列出字段与SELECT *相比,我可以期待什么类型的性能优势(如果有的话)?

我会这么说,这两个查询都利用了相同的确切索引。如果您想知道,更具体的查询无法访问其他查询无法使用的覆盖索引。

我不期待奇迹,就像添加一个针对更具体查询的索引一样。我是在想。

回答

7

它取决于三件事情:数据库使用的底层存储和检索机制,您要离开的7列的性质以及结果集中返回的行数。

如果您将要离开的7列(或任何数量)的列“便于检索”,并且返回的行数很少,那么我期望的效果很小。如果这些列是“昂贵的”(例如,它们很大,或者它们是需要引用另一个永远不会缓存的文件的BLOB),并且/或者您正在检索很多行,那么您可能会期望获得显着的改进。多少取决于在特定数据库中检索信息并在内存中进行汇编的成本。

除了速度之外,还有其他一些原因,顺便说一句,在检索信息时使用命名列与绝对知道某些列包含在结果集中并且列按照您希望使用它们的期望顺序英寸

-1

你为什么不尝试一下,让我们知道?

这一切都将取决于多少列和它们的宽度。

更好的是,你是否有实际的性能问题?告诉我们你的实际问题是什么,并告诉我们代码,然后我们可以建议潜在的改进。可能还有其他的改进要比担心SELECT *和SELECT字段列表要好得多。

1

我期望看到的主要区别是网络流量减少。如果任何一列很大,则可能需要一些时间进行传输,如果您不显示它们,这当然是一种完全浪费。

如果您的数据库库通过索引(而不是名称)引用列,这也是非常重要的,因为如果列顺序在数据库中更改,它将破坏代码。

编码风格明智,它允许您查看代码的其余部分将使用哪些列,而无需阅读它。

1

嗯,在一个简单的实验中,我惊讶于它造成了多大的差异。

我只是做有三个变化一个简单的查询:

  1. SELECT *
  2. 选择是主键字段。 (它可能会直接从索引中得到这个,而实际上没有读取记录)
  3. 选择一个非关键字段。

我用了一个有很多字段的表 - 其中72个 - 包括一个CLOB。该查询只是where子句中的一个条件选择。

结果:

 
Run *  Key Non-key 
1 .647 .020 .028 
2 .599 .041 .014 
3 .321 .019 .027 
avg .522 .027 .023 

重点与非重点似乎没有关系。 (这令我感到惊讶。)但是只检索一个字段与选择*保存了95%的运行时间!

当然这是一个表的一个小实验。可能有许多相关因素。我当然不会声称,通过不使用select *,您总会将运行时间减少95%!但它远远超出我的预期。

+0

您是否尝试先运行Non-Key或Key查询,以确保它们与'*'相比没有缓存好处?令人惊讶的是差异如此之大。 – 2010-10-05 22:28:23

+0

考虑到非关键列在第2次运行中比关键列回来要快得多(假设这不是错字),我认为缓存与速度的某些差异有关。 – 2010-10-05 23:00:24

+0

@Jonathan:我以不同的顺序多次运行它们,以避免因缓存而导致误导结果。我连续两次跑每一个,看看我是否会第二次得到不同的结果等。除了缓存另一个明显的问题是什么碰巧同时触及数据库。我当然不会声称我在这里的结果是明确的 - 只是有趣的。 – Jay 2010-10-06 14:06:58

1

当比较13 vs 20字段时,如果剩下的7个字段不是CLOB/BLOB等字段,我希望看到没有明显的性能增益。 I/O是主要的数据库瓶颈(大多数数据库系统是I/O绑定的),所以你可能会认为你会把执行时间缩短到原始查询执行时间的13/20(因为你需要的数据少得多) ),但由于普通字段存储在相同的物理结构中(通常字段连续排列)并且文件系统读取整个块,所以您的磁盘头将读取相同数量的数据(假设所有20个字段小于块大小;情况可以改变,如果一个记录的大小比你的文件系统块大)。

SELECT *不好的原因有不同的原因 - 系统的稳定性。

如果您在错误的地方使用SELECT *,那么对基础表的更改可能会意外地破坏您的系统(主要是以后的时间,如果事情破裂,通常情况下它们会更快破坏)。如果规范化数据(将列从一个表格移动到另一个表格,同时保持相同的名称),这尤其可能是有利的。在这种情况下,如果您在视图中链接SELECT *,并且链接了您的视图,那么您实际上可能不会收到任何错误,但具有(实质上)不同的最终结果。

-1

选择*表示数据库必须花时间查找字段。如果你不需要所有这些字段(并且任何时候你有一个内部联接,你不需要重复加入字段!),那么你就是在浪费服务器资源来获取数据和网络资源来传输数据。您可能也在浪费内存来保存记录集来处理它。尽管一个查询的性能改进可能很小,但查询运行了多少次?而使用这种极其糟糕的技术的人倾向于在任何地方使用它,因此,修复所有这些技术可以成为一项主要的努力,而不是付出太多的努力。并且指定这些字段有多难?我不知道每个数据库,但是在SQL Server中,我可以在几秒钟内从对象浏览器中拖放我想要的内容。因此,使用select *的交易时间不会超过一分钟的开发时间,因为每次运行查询时都会出现性能更差的情况,并且会创建易碎且易受架构更改的问题影响的代码。我没有理由在生产代码中使用select *。