前言,我知道(你应该!)在生产中使用SELECT *
是不好的,但我维护的是其他人编写的脚本。而且,我也知道这个问题在具体细节方面很低......但是假设情景。
假设我有一个脚本可以从20个字段的表中选择所有内容。让我们说一下典型的客户信息。
然后让我们说我是优秀的开发人员,我将SELECT *
缩短为我在显示端实际使用的13个特定字段中的SELECT
。
通过明确列出与SELECT *
相对应的字段,我可以期望获得哪种类型的效果好处?
我会这样说,两个查询都利用了相同的索引。如果您想知道,更具体的查询无法访问其他查询无法使用的覆盖索引。
我不期待奇迹,比如添加一个针对更具体查询的索引。我只是想知道。
答案 0 :(得分:7)
这取决于三件事:数据库使用的底层存储和检索机制,您要遗漏的7列的性质以及结果集中返回的行数。
如果你要遗漏的7(或任何数字)列是“便宜的检索”列,并且返回的行数很少,我预计收益很少。如果列“昂贵”(例如,它们很大,或者它们是BLOB需要引用另一个永远不会被缓存的文件)和/或您正在检索大量行,那么您可以期待显着的改进。具体取决于您在特定数据库中检索该信息并在内存中组装的成本。
除了速度之外还有其他原因,顺便提一下,在检索信息时使用命名列,这些信息与绝对知道结果集中包含某些列并且列是您想要在其中使用它们的所需顺序有关。
答案 1 :(得分:1)
我期望看到的主要区别是网络流量减少。如果任何列很大,它们可能需要一些时间来传输,如果你没有显示它们,这当然是完全浪费。
如果您的数据库库按索引(而不是名称)引用列,这也是非常关键的,因为如果数据库中的列顺序发生变化,它将破坏代码。
明智的编码风格,它允许您查看其余代码将使用哪些列,而无需阅读。
答案 2 :(得分:1)
我刚做了一个简单的查询,有三个版本:
我使用了一个包含大量字段的表 - 其中72个 - 包括一个CLOB。查询只是在where子句中有一个条件的select。
结果:
Run * Key Non-key 1 .647 .020 .028 2 .599 .041 .014 3 .321 .019 .027 avg .522 .027 .023
密钥与非密钥似乎并不重要。 (这让我感到惊讶。)但是只检索一个字段而不是select *节省了95%的运行时间!
当然,这是一个只有一张桌子的小实验。可能有许多相关因素。我当然没有声称你不会因为不使用select *而将运行时间减少95%!但它比我预期的更令人印象深刻。
答案 3 :(得分:1)
当比较13个字段和20个字段时,如果遗漏的7个字段不是CLOB / BLOB等字段,我希望看不到明显的性能提升。
I / O是主要的数据库瓶颈(大多数数据库系统都受I / O限制),因此您可能认为将执行时间延长到原始查询执行时间的13/20(因为您需要的数据少得多) ,但由于普通字段存储在同一物理结构中(通常字段连续排列)并且文件系统读取整个块,因此磁盘头将读取相同数量的数据(假设所有20个字段都小于块大小;情况可以如果记录的大小大于文件系统的块,则更改。)
SELECT *
坏的原则有不同的原因 - 系统的稳定性。
如果你在错误的地方使用SELECT *
,那么对基础表的更改可能会意外地破坏你的系统(大部分时间过后,如果事情中断,通常会更好地破坏它们)。如果规范化数据(将列从一个表移动到另一个表,同时保持相同的名称),这尤其有意义。在这种情况下,如果您在视图中链接SELECT *
并且链接您的视图,那么您实际上可能没有任何错误,但是(基本上)具有不同的最终结果。
答案 4 :(得分:-1)
为什么不亲自尝试并告诉我们?
这一切都将取决于它们的列数和宽度。
更好的是,您是否有实际的性能问题?告诉我们您的实际问题是什么,并向我们展示代码,然后我们可以建议潜在的改进。有可能做出其他改进,比担心SELECT *与SELECT字段列表要好得多。
答案 5 :(得分:-1)
选择*表示数据库必须花时间查找字段。如果您不需要所有这些字段(并且任何时候您都有内部联接,则不会重复连接字段!)然后您浪费了服务器资源来获取数据和网络资源来传输数据。您可能还在浪费内存来保存记录集以使用它。虽然一个查询的性能提升可能很小,但查询运行了多少次?使用这种极其糟糕的技术的人倾向于在任何地方使用它,因此修复所有这些技术可能是一项重要的改进,而不是那么多的努力。指定字段有多难?我不知道每个数据库,但在SQL Server中,我可以在几秒钟内从对象浏览器中拖放我想要的内容。因此,使用select *交换的开发时间不到一分钟,因为每次运行查询时性能都会更差,并且创建的代码很脆弱,并且在架构更改时会遇到非常严重的问题。我认为没有理由在生产代码中使用select *。