【问题标题】:Strange execution time for summary query摘要查询的奇怪执行时间
【发布时间】:2013-06-22 20:25:45
【问题描述】:

我在这里给出我正在执行的查询的一部分:

SELECT SUM(ParentTable.Field1),
       (SELECT SUM(ChildrenTable.Field1)
       FROM ChildrenRable INNER JOIN
           GrandChildrenTable ON ChildrenTable.Id = GrandChildrenTable.ChildrenTableId INNER JOIN
           AnotherTable ON GrandChildrenTable.AnotherTableId = AnotherTable.Id
       WHERE ChildrenTable.ParentBaleId = ParentTable.Id
       AND AnotherTable.Type=1),
       ----
FROM ParentTable
WHERE some_conditions

关系:

ParentTable -> ChildrenTable = 1-to-many
ChildrenTable -> GrandChildrenTable = 1-to-many
GrandChildrenTable -> AnotherTable = 1-to-1

我正在执行此查询 3 次,同时仅更改 Type 条件,结果如下:

返回的记录数:

Condition   Total execution time (ms)
Type = 1 :            973
Type = 2 :          78810
Type = 3 :         648318

如果我只执行内部连接查询,这里是连接记录的计数:

SELECT p.Type, COUNT(*)
FROM CycleActivities ca INNER JOIN
     CycleActivityProducts cap ON ca.Id = CAP.CycleActivityId INNER JOIN
 Products p ON cap.ProductId = p.Id
GROUP BY p.Type

Type 
---- -----------
1     55152
2     13401
4    102730

那么,为什么 Type = 1 条件的查询比 Type = 2 的查询执行得快得多,尽管它查询的是 4 倍大的结果集(类型是 tinyint)?

【问题讨论】:

    标签: stored-procedures sql-server-2012


    【解决方案1】:

    查询的编写方式指示 SQL Server 使用JOIN 对输出的每一行执行子查询。

    如果我正确理解您想要的内容,这样应该会更快(更新):

    with cte_parent as (
       select 
          Id,
          SUM (ParentTable.Field1) as Parent_Sum
    from ParentTable
    group by Id
    ), 
    
    cte_child as (
        SELECT
           Id,
           SUM (ChildrenTable.Field1) as as Child_Sum
        FROM ChildrenRable 
           INNER JOIN
               GrandChildrenTable ON ChildrenTable.Id = GrandChildrenTable.ChildrenTableId 
           INNER JOIN
               AnotherTable ON GrandChildrenTable.AnotherTableId = AnotherTable.Id
        WHERE 
               AnotherTable.Type=1
           AND
               some_conditions
        GROUP BY Id
    )
    
    select cte_parent.id, Parent_Sum, Child_Sum
    from parent_cte 
    join child_cte on parent_cte.id = child_cte.id
    

    【讨论】:

    • 嗨,Stoleg,您不能像这样在 ParentTable.Field1 上进行分组,因为它会根据加入的记录数乘以结果。这同样适用于 SUM(ChildrenTable.Field1。唯一能正常工作的是如果你做了 SUM(GrandChildrenTable.Field1)。
    • 我的猜测是您对输出中的不止一行感兴趣,对吧?如果是这样,每一行输出将是一个(在简单情况下)属性的摘要。您需要将数字相加的列是什么?或者您只需要 1 行中的所有内容?
    • 我感兴趣的内容并不重要,因为您编写的查询在任何情况下都是不正确的。让我更准确地说:假设您在 ParentTable 中有 1 条记录,ParentTable.field1 = 200,并且您在 ChildrenTable 中有两条记录,每条记录在 GrandChildren 表中都有一个引用记录。当您执行您编写的查询时,SUM(ParentTbale.Field1) 将返回 2x200=400,而不是 200,这是不正确的。
    猜你喜欢
    • 2019-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多