小编典典

使用COUNT(*)或SELECT *是个好主意吗?

sql

我已经多次听到您不应该执行COUNT(*)SELECT *出于性能方面的考虑,但是无法深入了解有关它的更多信息。

我可以想象数据库随后将 所有 列都用于操作,这可能会导致性能下降,但是我不确定。有人有关于该主题的更多信息吗?


阅读 242

收藏
2021-05-05

共1个答案

小编典典

1.关于count(*)vs. count(其他)

SQL是声明性的,您可以指定所需的 内容 。这不同于指定 如何
获得所需的东西。这意味着数据库引擎可以自由地以其认为最有效的方式来实现您的查询。许多数据库优化器将您的查询重写为成本较低的替代方法(如果有这样的计划可用)。

给出下表:

table(
   pk       not null
  ,color    not null
  ,nullable null
  ,unique(pk)
  ,index(color)
);

…以下 所有 功能在功能上都是等效的(由于 countnull的机制 ):

1) select count(*) from table;
2) select count(1) from table;
3) select count(pk) from table;
4) select count(color) from table;

无论使用哪种形式,优化器都可以自由地将查询重写为另一种形式(如果更有效)。(同样,并非所有优化器都足够复杂以执行此操作)。唯一索引(pk)将小于整个表(占用的字节数)。因此,计算索引条目的数量比扫描整个表会更有效。在Oracle中,我们有位图索引,该索引还压缩重复的字符串。如果我们在颜色列上使用了这样的索引,则它可能是要扫描的最小索引。Oracle还支持表压缩,这在某些情况下使物理表小于复合索引。

1. TL; DR;
您的特定dbms将具有自己的工具集,该工具集可启用不同的重写规则并进而执行计划。这使该问题变得毫无用处(除非我们谈论特定dbms的特定发行版)。我建议COUNT(*)在所有情况下都使用它,因为它需要最少的认知努力。

2.在选择a,b,c与选择*

您* 编写并投入生产的SELECT *代码很少有有效的用途。想象一个包含Bluray电影的表(是的,这些电影在该表中存储为blob)。因此,您将您的真棒酱抽象层拍打在一起并放入了该方法。我不会解释为什么会以更快的速度跨网络传输。当然,在大多数实际情况下,它不会产生明显的影响。
*SELECT * FROM movies where id = ?``getMovies(movie_id)``SELECT name FROM movies

关于性能的最后一点是,当查询中所有引用的列(已选择,已过滤)作为索引(称为覆盖索引)存在时,数据库根本不需要触摸表。仅扫描索引即可完全解决此问题。通过选择所有列,可以从优化器中删除此选项。

另一个SELECT *要比任何事情都严重的事情是,它对表的特定物理布局产生了隐式依赖。让我解释。请考虑以下表格:

table T1(name, id)
table T2(name, id)

以下声明…

insert into t1 select * from t2;

如果发生以下任何一种情况,将会打破或产生不同的结果:

  • 表中的任何一列都会重新排列,例如T1(id,name)
  • T1获得一个附加的非空列
  • T2进入另一列

2. TL; DR;
在可能的情况下,明确指定所需的列(最终,无论如何都必须这样做)。同样,选择更少的列比选择更多的列要快。显式选择的一个可能的副作用是,它为优化器提供了更大的自由度。

2021-05-05