9

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

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

4 回答 4

5

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

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

于 2012-06-07T13:04:00.310 回答
2

Are you sure? Maybe the second query is just using cached resources from the first on.

run them in two separately batches and before each one run DBCC FREEPROCCACHE to clean the cache. Then compare the values of each execution plan.

于 2012-06-07T13:16:50.500 回答
0

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

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

于 2012-06-07T13:34:42.897 回答
0

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

正如所写的那样,联合会天真地要求两次遍历数据,进行过滤和计数。基本上不需要其他存储。

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

如果你有关于性别的索引,这两种方法本质上都会扫描索引,所以性能应该是相似的(联合版本可能会扫描两次=.

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

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

于 2012-06-07T13:12:39.863 回答