2

嘿,我有以下表格和 SQL:

T1:ID、col2、col3 - PK(ID) - 2300 万行

T2:ID、col2、col3 - PK(ID) - 2300 万行

T3: ID, name,value - PK(ID,name) -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, 

这两个查询之间的显示计划的唯一区别是查询 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)如何在保持查询逻辑相同的同时进行修复,最好像以前一样将其限制为 1 选择 SQL。

谢谢你

4

1 回答 1

1

虽然可能是一个通用的答案,但我会说在您分组的列上放置一个索引。

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

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

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

IE

    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
于 2011-04-01T20:29:23.857 回答