性能"SELECT *"与"SELECT <one_column>"



我有person如下:

person表:

id 第一名称 姓氏 年龄
1 约翰 史密斯 23
2 大卫 棕色 18

这里的问题与其说是数据库服务器的问题,不如说是网络通信的问题。通过一次选择所有列,您告诉服务器一次返回给您,所有列至于对IO的担忧,@Karamba在评论中给出的问答很好地解决了这些问题:select*vs select column。但对于大多数现实世界中的应用程序(我在各种意义上都使用"应用程序"(,主要关注的只是网络流量以及串行化、传输和反序列化数据所需的时间。尽管事实上,无论哪种方式,答案都是一样的。

因此,如果您打算全部使用所有列,那么收回所有列是很好的,但这可能会带来大量额外的数据传输,特别是如果您在列中存储(例如(长字符串。当然,在许多情况下,这种差异是无法检测到的,而且大多只是原则问题。不是全部,但绝大多数。

这实际上只是你前面提到的懒惰(相信我,我们都有这种感觉(和性能的重要性之间的权衡

也就是说,如果确实打算使用所有列值,那么最好一次将它们全部取回来,然后再提交一堆查询。

把它想象成网络搜索:你进行搜索,找到你的页面,你只需要一个细节。你可以阅读整页,了解关于这个主题的一切,也可以直接跳到你想要做什么的部分。如果这就是你想要的,后者会快得多,但如果你必须了解其他方面,你最好第一次阅读它们,而不是再次搜索并找到网站来谈论它。

如果您不确定将来是否需要其他列值,那么这是您作为开发人员的决定,在这种情况下更有可能。

这完全取决于您的应用程序是什么,数据是什么,您如何使用它,以及性能对您的重要性。

选择单列会对某些查询的性能产生很大影响。例如,查询引擎处理索引比在原始数据页中查找数据更高效。如果覆盖索引可用,即包含查询所需的所有列的索引,那么查询将运行得更快。对于对于可用内存来说太大的大表,使用覆盖索引可能是一个巨大的胜利。(在某些情况下,性能可以提高几个数量级。(

当列的数量有限时,另一种情况是当一个或多个列非常大时,例如BLOB或TEXT列。它们的大小可以增长到数万字节甚至兆字节。检索它们并给服务器带来很大的负载。

如果您已经准备好了语句并且表的底层结构发生了更改,那么使用*是有危险的。查询本身可能会过时(我在其他数据库上也遇到过这个问题,但在MySQL上没有遇到(。潜在的更改可以像更改列的名称一样简单。相反,被捕获为编译时错误的是一个可能更神秘的运行时错误。

一般来说,避免*的原因更多地与网络性能有关。在许多情况下,这不会有多大区别。如果您从一个表中返回20行,其中每行平均包含100或200个字节,那么在大多数硬件环境中,选择所有列和列的子集之间的差异将很小。用于查询的绝大多数时间将用于编译查询、在引擎中执行查询以及读取数据页。返回200字节和2000字节之间的区别可能不会太大。

然而,在某些情况下(例如上面列出的情况(,它可以产生很大的影响。因此,避免*是一个好习惯,但偶尔使用它可能不会降低你的系统。

至少在PostgreSQL中,选择一列的性能要快于所有列的性能。

PostgreSQL中,我创建了test,其中10个id_x1000万行如下所示:

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个查询,总共运行了6次*每个查询总共运行3次

SELECT * FROM test;
SELECT id_1 FROM test;

<结果>

SELECT * FROM test;SELECT id_1 FROM test;
第一次运行13.817秒2.634秒
第二次运行13.579秒2.606秒
第三次运行1.341秒2.611秒
平均13.579秒2.617秒

最新更新