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

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

SELECT * FROM TABLE

or

SELECT column1, colum2, column3, etc. FROM TABLE

在这种情况下,效率真的重要吗?如果你真的需要所有的数据,我认为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秒。

其他回答

两者之间的主要区别是来回传递的数据量。任何关于时间差的争论在“select *”和“select col1,…”, colN”会导致DB引擎执行相同数量的相对工作。但是,每行传输15列与每行传输5列是10列的差异。

选择特定列更好的一个原因是,它提高了SQL Server从索引访问数据的概率,而不是查询表数据。

这是我写的一篇关于它的文章:选择查询的真正原因是糟糕的索引覆盖

它也不太容易更改,因为任何消耗数据的代码都将获得相同的数据结构,而不管您将来对表模式做了什么更改。

结果太大了。从SQL引擎生成结果并将结果发送到客户机的速度很慢。

客户端是一个通用的编程环境,不是也不应该被设计为过滤和处理结果(例如WHERE子句,ORDER子句),因为行数可能非常大(例如数千万行)。

上面所有人说的,加上:

如果你正在努力编写可读性强、可维护的代码,可以这样做:

SELECT foo, bar FROM widgets;

立即可读并显示意图。如果你打了那个电话,你知道你会得到什么。如果widget只有foo和bar列,那么选择*意味着您仍然需要考虑返回什么,确认顺序映射正确等等。然而,如果widget有更多的列,但您只对foo和bar感兴趣,那么当您查询通配符,然后只使用返回的部分内容时,您的代码就会变得混乱。

您实际上应该只选择您需要的字段,并且只选择所需的数量,即。

SELECT Field1, Field2 FROM SomeTable WHERE --(constraints)

在数据库之外,动态查询有注入攻击和畸形数据的风险。通常使用存储过程或参数化查询来解决这个问题。而且(虽然不是真正的大问题)服务器必须在每次执行动态查询时生成一个执行计划。