Sybase专家帮助:groupby聚合性能问题

时间:2011-04-01 20:07:55

标签: performance group-by sybase case-when

嘿,我有以下表格和SQL:

T1:ID,col2,col3 - PK(ID) - 23mil行

T2:ID,col2,col3 - PK(ID) - 23mil行

T3:ID,名称,值 - PK(ID,名称)-66mil行

1)下面的sql非常快速地返回10k行结果集,没有问题。

select top 10000 T1.col2, T2.col2, T3.name, T4.value 
from T1, T2, T3  
where T1.ID = T2.ID and T1.ID *= T3.ID and T3.name in ('ABC','XYZ') 
and T2.col1 = 'SOMEVALUE'

2)下面的sql取得了永远。

select top 10000 T1.col2, T2.col2, 

ABC  = min(case when T3.name='ABC ' then T3.value end)  
XYZ  = min(case when T3.name='XYZ ' then T3.value end)  

from T1, T2, T3  

where T1.ID = T2.ID and T1.ID *= T3.ID and T3.name in ('ABC','XYZ')
and T2.col1 = 'SOMEVALUE'

group by T1.col2, T2.col2, 

这两个查询之间showplan的唯一区别在于查询2的以下内容。我不理解它100%,它是否在临时表中选择了没有前10000的整个结果集,然后在它上面进行分组?这就是为什么它很慢?

STEP 1
    The type of query is SELECT (into Worktable1).
    GROUP BY
    Evaluate Grouped MINIMUM AGGREGATE.

    FROM TABLE ...etc..

    TO TABLE
        Worktable1.

STEP 2
    The type of query is SELECT.

    FROM TABLE
        Worktable1.
    Nested iteration.
    Table Scan.
    Forward scan.
    Positioning at start of table.
    Using I/O Size 16 Kbytes for data pages.
    With MRU Buffer Replacement Strategy for data pages.

我的问题是

1)为什么查询2)这么慢

2)如何在保持查询逻辑相同的情况下进行修复,并且最好将其限制为仅像以前一样选择SQL。

谢谢

1 个答案:

答案 0 :(得分:1)

虽然可能是一般性答案,但我会说要对你要分组的列进行索引。

编辑/修改:重新审视此问题后,这是我的理论。查询中的SELECT语句始终是最后执行的行。这是有道理的,因为它是从下面指定的数据集中检索所需值的语句。在查询中,将针对您指定的MIN值表达式评估整个数据集(数百万条记录)。由于您在select语句中指定了两个MIN列,因此将在整个数据集上调用两个单独的函数。 过滤数据集并确定MIN列后,将选择前10000行。

简而言之,你在数百万条记录上做了两个数学函数。这将花费大量时间,尤其是在没有索引的情况下。

您的解决方案是使用派生表。我没有编译下面的代码,但它与您将使用的内容很接近。它只需要10,000个记录的最小值而不是整个数据集。

即。

    Select my_derived_table.t1col2, my_derived_table.t2col2,
    ABC  = min(case when my_derived_table.t3name ='ABC ' then my_derived_table.t3value end),  
    XYZ  = min(case when my_derived_table.t3name='XYZ ' then my_derived_table.t3value end)
    FROM
      (Select top 10000 T1.col2 as t1col2, 
              T2.col2 as t2col2, 
              t3.name as t3name, 
              t3.value as t3.value
       from T1, T2, T3
       where T1.ID = T2.ID 
         and T1.ID *= T3.ID 
         and T3.name in ('ABC','XYZ')
         and T2.col1 = 'SOMEVALUE') my_derived_table
group by my_derived_table.t1col2, my_derived_table.t2col2