2012-06-07 42 views
8

好吧,也许我太老了,我想了解以下内容。为什么一个工会比一个组的速度快

查询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%。

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

+1

只是一个猜测:第二个查询实际上有没有聚集,没有状态保持以计算计数(它只是返回匹配的行数'COUNT(*)') – lanzz

+0

你是什么意思'在同一时间? – Sebas

+2

我想你只有2个性别和每个人都有分配,而不是一些被'NULL'性别?另外如果你尝试'联盟所有'?这会进一步提高第二个吗?还有什么RDBMS和执行计划是什么样的?在SQL Server执行计划中,相对成本也不一定反映真实的性能,如果这是您用来比较这两个查询。 –

回答

5

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

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

+0

关于性别指数可以用于在第一查询流聚集了。不需要排序,因为它们已经处于索引顺序。 –

+0

是的,但这些行需要解码并相互比较。 – usr

+0

该行需要在一个索引查找过,知道要被解码时,它已经到达最后一行匹配寻求谓语,应停止扫描。 –

0

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

如书面所述,联合会天真地需要两次通过数据,做一个过滤器和一个计数。基本上不需要其他存储。

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

如果您有关于性别的指标,这两种方法将基本上扫描索引所以性能应该是相似的(工会版本可能扫描两次=

是否正在使用提供了一种数据库如果是这样,你应该更新统计数据,看看你是否仍然得到相同的结果。

另外,你可以发布“解释”的结果或执行计划吗?这正好可以解释为什么一个是比其他更快

2

Are you sure? 也许第二个q uery只是从第一个使用缓存的资源。

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

+1

这也是我的猜测 – Filip

0

我试过一个等价的查询,但发现相反的结果;工会占了65%,而“小组靠”占了35%。 (使用SQL Server 2008)。我没有性别索引,因此我的执行计划显示聚集索引扫描。除非详细检查执行计划,否则不可能解释这个结果。

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

相关问题