为什么一个联盟比一个组更快

时间:2012-06-07 12:54:06

标签: sql

好吧,也许我太老了,我想了解以下内容。

查询1。

select count(*), gender from customer
group by gender

查询2.

select count(*), 'M' from customer
where gender ='M'
union
select count(*), 'F' from customer
where gender ='F'

第一个查询更简单,但由于某些原因在分析器中,当我同时执行两个查询时,它表示查询2使用39%的时间,查询1,61%。

我想了解原因,也许我必须重写所有查询。

4 个答案:

答案 0 :(得分:5)

您的查询2实际上是一个很好的技巧。它的工作原理如下:你有一个性别指数。 DBMS可以搜索该索引两次以获得两个行范围(一个用于M,一个用于F)。它不需要从这些行中读取任何内容,只是它们存在。它可以计算两个范围中存在的行数。

在第一个查询中,DBMS需要对行进行解码以读取性别,然后需要对行进行排序或构建哈希表来聚合它们。这比计算行更昂贵。

答案 1 :(得分:2)

你确定吗? 也许第二个查询只是使用第一个查询中的缓存资源。

分别在两个批处理中运行它们,然后在每个批处理运行DBCC FREEPROCCACHE之前清理缓存。然后比较每个执行计划的值。

答案 2 :(得分:0)

查询的优化取决于数据库。您所看到的是特定于数据库的。

正如所写的那样,联盟将天真地要求两次通过数据,进行过滤和计数。基本上不需要其他存储空间。

聚合可能会对数据进行排序,然后进行计数。或者,它可能会生成哈希表。鉴于性能差异,我猜测正在使用一种类型。显然,对于这种类型的查询来说这是过度的。

如果你有性别索引,两种方法都会扫描索引,因此性能应该相似(联合版本可能会扫描两次=。

您使用的数据库是否提供了计算表统计信息的方法?如果是这样,您应该更新统计信息,看看是否仍然得到相同的结果。

另外,您可以发布“解释”或执行计划的结果吗?这可以准确地解释为什么一个比另一个更快。

答案 3 :(得分:0)

我尝试了一个等效的查询,但发现了相反的结果;工会占65%,'group by'占35%。 (使用SQL Server 2008)。我没有关于性别的索引,因此我的执行计划显示了聚集索引扫描。除非您详细检查执行计划,否则无法解释此结果。

为此查询添加索引可能不是一个好主意,因为您可能不会像在客户表中插入记录那样频繁地运行此查询。在其他一些带位图索引的数据库引擎(Oracle,PostgreSQL)中,数据库引擎可以组合多个索引,这样可以改变单列索引的效用。但是在SQL Server中,您需要设计索引以“覆盖”常用查询。