SELECT * 真的比只选择需要的列花费更多的时间吗?

Posted

技术标签:

【中文标题】SELECT * 真的比只选择需要的列花费更多的时间吗?【英文标题】:Does SELECT * really take more time than selecting only the needed columns? 【发布时间】:2014-04-18 14:31:48 【问题描述】:

它会对网站页面的加载时间产生明显的影响吗?平均而言,我的表有 10 列,如果我只需要其中的 3 列,我是否应该在查询中调用这些列以使其更快?

【问题讨论】:

您从基准测试中看到了什么? 时间差异可能很小,并且可能被其他因素淹没,因此用户可能不会单独注意到(但它可能会与多个用户相加并变得至关重要)。如果您返回大量不需要的数据(例如存储在字段中的图像),则可能是主要例外。然而,调试、维护和可靠性可能是避免使用 SELECT * 的更好理由。 0.723 秒 vs 0.0717 秒的表格,我总结了三列和 131,563 行数据。那不是没有区别吗? 这是一个 10 倍的时间差异,这比我通常预期的要多得多。但正如其他人在下面指出的那样,这将取决于确切的条件。如果您从远程服务器检索并且(例如)返回了几个 TEXT 列,而您不需要这些列的值,那么时间差可能会很大。 【参考方案1】:

它会产生可识别的不同吗?在大多数情况下可能不会。以下是一些可能会产生重大影响的情况:

7 个不需要的列非常非常大。 您要返回很多很多行。 您有一张大表,有很多行,并且 3 列上的索引可用,但 10 列上没有。

但是,还有其他不使用*的原因:

它将根据编译查询时数据库中列的顺序替换列。如果表的结构发生变化,这可能会导致问题。 如果列名更改或被删除,您的查询将正常工作,后续代码可能会中断。如果您明确列出列,则查询将中断,从而更容易发现问题。 键入三个列名应该没什么大不了的。明确列出列可以使代码提供更多信息。

【讨论】:

关于订购和意外密码破解的要点。如果您正在访问非关联数组中的数据(例如 php 中的 $row[0]),这也是一个问题——代码可能不会中断,但您可能会得到意想不到的结果。想象一下表 name, credit_card_number, email 正在被查询以显示用户的电子邮件地址,并且有人在name 之后添加了一个列,现在echo $row[2] 显示了信用卡号【参考方案2】:

假设您有一个包含 1000 列的表,而您只需要 3 个。

你认为什么会跑得更快,为什么?

这个:SELECT * FROM table_name;

或者这个:SELECT col1, col2, col3, FROM table_name;

当您使用* 时,您现在将整个选择(大或小)保存在内存中。选择越大......它将使用/需要的内存越多。

因此,即使您的表不一定很大,我仍然只会选择您实际需要的数据。您甚至可能没有注意到速度上的差异,但它肯定会更快。

【讨论】:

【参考方案3】:

是的,如果您只需要几列,请只选择那些。以下是一些原因:

    最明显的: 需要将额外的数据发回,以便传输更大的数据包(或通过本地套接字进行管道传输)。这将增加整体延迟。这对于 1 或 2 行来说可能看起来不多,但等到你有 100 或 1000 行...... 7 额外的数据列将显着影响整体传输延迟,特别是如果你最终不得不破坏结果集成更多的 TCP 数据包进行传输。如果您使用的是本地主机套接字,这可能不是这样的问题,但是将您的数据库移动到网络上的服务器、另一个数据中心等......并且影响将是显而易见的! 启用 mysql 查询缓存后,在结果集中存储不需要的数据会增加您的缓存空间需求 - 更大的查询缓存可能会影响性能。 一个巨大的打击可能是:如果您只需要作为覆盖索引一部分的列,则执行select * 将需要对主表中的剩余数据字段进行后续点查找,而不仅仅是使用索引表中的数据。

【讨论】:

【参考方案4】:

是的,你应该这样做。

在 select 中使用命名列是使用数据库的最佳实践,原因有很多。

只有需要的数据从数据库传输到应用服务器,从而减少 CPU、内存和磁盘的使用。

它有助于检测编码错误和结构变化。

只有少数情况下使用 select * 是个好主意,在所有其他查询中帮自己一个忙并使用列名。

【讨论】:

【参考方案5】:

是的,当然。 * 将被所有列名替换。之后只有执行开始。例如,如果一个表中有 3 列 a、b、c.. select a、b、c 直接开始执行,而 select * 开始将查询转换为 select a、b、c 之后只有执行统计信息。

【讨论】:

【参考方案6】:

简而言之,是的,如果您要返回更多数据,则需要更长的时间。这可能是一个非常非常非常小的时间,但是是的,它需要更长的时间。如上所述,在您可能不是设计/实现数据库的人的生产情况下,select * 可能很危险。如果您假设列按特定顺序返回或数据库结构属于特定类型,然后 DBA 进入并进行某种更改并且没有通知您,则您的代码可能有问题。

【讨论】:

【参考方案7】:

差异很小,但有细微的差异,我认为这取决于几个因素,哪个更快。

1) 表中有多少列?

2)您实际需要抓取多少列?

3)你抓取了多少条记录?

在你的情况下,根据你所说的有 10 列并且只需要其中 3 列,我怀疑如果你使用 'Select *' 会有所不同,除非你可能会抓住成千上万的记录。但在涉及更多列的更极端的情况下,我发现'Select *' 会稍微快一些,但这可能并非在所有情况下都是如此。

我曾经在一个包含 150 多列的 SQLite 表中进行了一些速度测试,我只需要抓取大约 40 列,并且需要全部 20,000 多条记录。速度差异非常小(我们说的是 20 到 40 毫秒的差异),但实际上使用 'SELECT ALL *' 从所有列中获取数据比使用 'Select All Field1, Field2, etc' 更快。

我假设你的表中的记录和列越多,这个例子的速度差异就越大。但是,如果您只需要一张大表中的 3 列,我猜只抓取这 3 列会更快。

不过,如果您真的关心 'Select *''Select field1, field2, etc' 之间的最小速度差异,那么请进行一些速度测试。

【讨论】:

以上是关于SELECT * 真的比只选择需要的列花费更多的时间吗?的主要内容,如果未能解决你的问题,请参考以下文章

XmlHttpRequest 在 IE 中是不是比在 Chrome 中花费更多时间?

提高 SQL Server 中最新记录的选择和插入性能

DELETE 查询是不是与 SELECT 花费相同的时间

从R数据表中选择特定的列

查询以选择某些条件为真的两个日期之间的列的总和

UNION运算符