我听说在编写SQL命令时使用SELECT *通常是不好的做法,因为选择您特别需要的列会更有效。

如果我需要选择表中的每一列,我应该使用

SELECT * FROM TABLE

or

SELECT column1, colum2, column3, etc. FROM TABLE

在这种情况下,效率真的重要吗?如果你真的需要所有的数据,我认为SELECT *在内部会更优,但我这么说并没有真正理解数据库。

我很好奇在这种情况下最好的做法是什么。

更新:我可能应该指定,我真正想要执行SELECT *的唯一情况是,当我从一个表中选择数据时,我知道总是需要检索所有列,即使添加了新列。

然而,鉴于我所看到的反应,这似乎仍然是一个坏主意,由于我曾经考虑过的许多技术原因,SELECT *不应该被使用。


当前回答

记住,如果根据定义有一个内部连接,则不需要所有列,因为连接列中的数据是重复的。

It's not like listing columns in SQl server is hard or even time-consuming. You just drag them over from the object browser (you can get all in one go by dragging from the word columns). To put a permanent performance hit on your system (becasue this can reduce the use of indexes and becasue sending unneeded data over the network is costly) and make it more likely that you will have unexpected problems as the database changes (sometimes columns get added that you do not want the user to see for instance) just to save less than a minute of development time is short-sighted and unprofessional.

其他回答

当且仅当需要获取所有字段的数据时,使用显式字段名并不比使用*更快。

你的客户端软件不应该依赖于返回字段的顺序,所以这也是毫无意义的。

而且有可能(尽管不太可能)需要使用*获取所有字段,因为您还不知道存在哪些字段(考虑非常动态的数据库结构)。

使用显式字段名的另一个缺点是,如果字段名很多而且很长,那么阅读代码和/或查询日志就会更加困难。

所以规则应该是:如果你需要所有的字段,使用*,如果你只需要一个子集,显式命名它们。

如果记录要遍历internet,那么限制返回的列可以大大提高性能。

“select *”的问题在于可能会带来您并不真正需要的数据。在实际的数据库查询期间,所选列并不会真正增加计算量。真正“繁重”的是将数据传输回客户端,任何您并不真正需要的列都只会浪费网络带宽,并增加等待查询返回的时间。

即使您确实使用了来自“select *…”的所有列,这也只是暂时的。如果将来您更改表/视图布局并添加更多列,您将开始在您的选择中引入这些列,即使您不需要它们。

“select *”语句不好的另一个地方是视图创建。如果您使用“select *”创建了一个视图,然后向表中添加列,则视图定义和返回的数据将不匹配,您需要重新编译视图以使它们再次工作。

我知道写一个“选择*”是诱人的,因为我真的不喜欢手动指定所有的字段在我的查询,但当你的系统开始发展,你会发现这是值得花额外的时间/精力在指定字段,而不是花更多的时间和精力消除错误在你的视图或优化你的应用程序。

总之,至少在PostgreSQL中,选择所有带*和不带*的列的性能几乎是一样的。

在PostgreSQL中,我创建了包含10个id_x列和1000万行的测试表,如下所示:

CREATE TABLE test AS SELECT generate_series(1, 10000000) AS id_1,
                            generate_series(1, 10000000) AS id_2,
                            generate_series(1, 10000000) AS id_3,
                            generate_series(1, 10000000) AS id_4,
                            generate_series(1, 10000000) AS id_5,
                            generate_series(1, 10000000) AS id_6,
                            generate_series(1, 10000000) AS id_7,
                            generate_series(1, 10000000) AS id_8,
                            generate_series(1, 10000000) AS id_9,
                            generate_series(1, 10000000) AS id_10;

然后,我交替运行以下2个查询共20次。*每个查询总共运行10次:

SELECT * FROM test:
SELECT id_1, id_2, id_3, id_4, id_5, id_6, id_7, id_8, id_9, id_10 FROM test;

结果> <

Select all columns with * Select all columns without *
1st run 12.792 seconds 12.483 seconds
2nd run 12.803 seconds 12.608 seconds
3rd run 12.537 seconds 12.549 seconds
4th run 12.512 seconds 12.457 seconds
5th run 12.570 seconds 12.487 seconds
6th run 12.508 seconds 12.493 seconds
7th run 12.432 seconds 12.475 seconds
8th run 12.532 seconds 12.489 seconds
9th run 12.532 seconds 12.452 seconds
10th run 12.437 seconds 12.477 seconds
Average 12.565 seconds 12.497 seconds

选择所有列的平均值:

*是12.565秒。 没有*是12.497秒。

对服务器来说,指定列名肯定更快。但是,如果

性能不是大问题(例如,这是一个网站内容数据库,每个表中有数百行,可能是数千行,但不是数百万行);和 你的工作是使用公共框架创建许多小型的类似应用程序(例如面向公众的内容管理网站),而不是创建一个复杂的一次性应用程序;和 灵活性很重要(为每个站点定制大量的db模式);

那么你最好坚持使用SELECT *。在我们的框架中,大量使用SELECT *允许我们将一个新的网站托管内容字段引入到一个表中,赋予它CMS的所有好处(版本控制、工作流/审批等),同时只在几个点上修改代码,而不是几十个点。

我知道DB专家们会因此而恨我——请继续,投我反对票——但在我的世界里,开发人员的时间是稀缺的,而CPU周期是丰富的,所以我相应地调整我所节省的和浪费的。