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

Bob*_*bby 6 sql database

我曾多次听说你不应该执行COUNT(*)SELECT *出于性能原因,但是无法进一步了解有关它的更多信息.

我可以想象数据库然后使用所有列进行操作,这可能是令人印象深刻的性能损失,但我不确定.有人有关于该主题的进一步信息吗?

Ron*_*nis 12

1.计数(*)与计数(其他)

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

鉴于下表:

table(
   pk       not null
  ,color    not null
  ,nullable null
  ,unique(pk)
  ,index(color)
);
Run Code Online (Sandbox Code Playgroud)

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

1) select count(*) from table;
2) select count(1) from table;
3) select count(pk) from table;
4) select count(color) from table;
Run Code Online (Sandbox Code Playgroud)

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

1. TL; DR; 您的特定dbms将拥有自己的一组工具,可以启用不同的重写规则以及执行计划.这使得这个问题有些无用(除非我们讨论特定dbms的特定版本).我建议COUNT(*)在所有情况下,因为它需要最少的认知努力来掌握.

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

编写并投入生产的SELECT *代码中的有效用途非常少.想象一下包含Bluray电影的表格(是的,电影在此表中存储为blob).所以,你拼凑你awesomesauce抽象层,并把在方法.我将不再解释为什么将会更快地通过网络传输.当然,在大多数现实情况下,它不会产生明显的影响.SELECT * FROM movies where id = ?getMovies(movie_id)SELECT name FROM movies

性能的最后一点是,当查询中所有引用的列(选中,已过滤)作为索引(称为覆盖索引)存在时,数据库根本不需要触及该表.只能通过扫描索引完全解决.通过选择所有列,您可以从优化程序中删除此选项.

另一件事情SELECT *比任何事情都要严重得多,它会对表格的特定物理布局产生隐含的依赖关系.让我解释.请考虑以下表格:

table T1(name, id)
table T2(name, id)
Run Code Online (Sandbox Code Playgroud)

以下声明......

insert into t1 select * from t2;
Run Code Online (Sandbox Code Playgroud)

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

  • 任何表列都重新排列,例如T1(id,name)
  • T1获得一个额外的非空列
  • T2得到了另一个专栏

2. TL; DR; 如果可能,请明确指定所需的列(最终,您必须这样做).此外,选择较少的列比选择更多列更快.对显式选择的可能副作用是它为优化器提供了更大的自由度.

  • @汤姆.我不明白这是恭维还是侮辱,但徽章是徽章;) (5认同)

Pat*_*rez 6

COUNT(*)不同于COUNT(column1)!
COUNT(*)返回记录数,并且不使用更多资源,同时COUNT(column1)计算column1为非null的记录数.

因为SELECT,它是不同的.SELECT *当然会要求更多数据.