2013-01-08 34 views
14

我有下面的SQL查询运行非常缓慢。我看了一下执行计划,声称在Files.OrderId上进行排序是成本最高的操作(53%)。为什么会发生这种情况,如果我没有通过OrderId在任何地方订购?我最好在File.OrderId上创建索引吗?为什么我的执行计划中会出现排序?

Execution plan如果有人有兴趣。

with custOrders as 
(
    SELECT c.firstName + ' ' + c.lastname as Customer, c.PartnerId , c.CustomerId,o.OrderId,o.CreateDate, c.IsPrimary 
    FROM Customers c 
    LEFT JOIN CustomerRelationships as cr 
     ON c.CustomerId = cr.PrimaryCustomerId 
    INNER JOIN Orders as o 
     ON c.customerid = o.customerid 
      OR (cr.secondarycustomerid IS NOT NULL AND o.customerid = cr.secondarycustomerid) 
    where c.createdate >= @FromDate + ' 00:00' 
     AND c.createdate <= @ToDate + ' 23:59' 
), 
temp as 
(
SELECT Row_number() 
     OVER ( 
      ORDER BY c.createdate DESC)     AS 'row_number', 
     c.customerid as customerId, 
     c.partnerid as partnerId, 
     c.Customer, 
     c.orderid as OrderId, 
     c.createdate as CreateDate, 
     Count(f.orderid)         AS FileCount, 
     dbo.Getparentcustomerid(c.isprimary, c.customerid) AS ParentCustomerId, 
     au.firstname + ' ' + au.lastname     AS Admin, 
     '' as blank, 
     0 as zero 
FROM custOrders c 
     INNER JOIN files f 
       ON c.orderid = f.orderid 
     INNER JOIN admincustomers ac 
       ON c.customerid = ac.customerid 
     INNER JOIN adminusers au 
       ON ac.adminuserid = au.id 
     INNER JOIN filestatuses s 
       ON f.statusid = s.statusid 
WHERE ac.adminuserid IS NOT NULL 
     AND f.statusid NOT IN (5, 6) 
GROUP BY c.customerid, 
      c.partnerid, 
      c.Customer, 
      c.isprimary, 
      c.orderid, 
      c.createdate, 
      au.firstname, 
      au.lastname 
) 
+0

*错误在验证源XML * – Kermit

+0

是的,我看到了。它真的有所作为吗?你仍然可以看到XML ... –

+0

不是'OVER'意味着什么? – Kermit

回答

11

SQL Server有三种算法从当它需要连接两个表来选择。嵌套循环加入,哈希加入和排序合并加入。它根据成本估算选择它。在这种情况下,它认为,基于它可用的信息,Sort-Merge-Join是正确的选择。

在SQL Server执行计划排序合并是splitt成两个运营商来说,排序和融合连接,因为排序操作可能不是必要的,例如,如果数据已经排序。

如需更多有关加入这里看看我的加盟系列:http://sqlity.net/en/1146/a-join-a-day-introduction/ 有关排序-MERG-加入的文章是在这里:http://sqlity.net/en/1480/a-join-a-day-the-sort-merge-join/


为了使您的查询速度更快,我首先会看指数。查询中有一堆聚集索引扫描。如果你可以用寻求代替其中的一小部分,那么你最有可能更好。同时检查SQL Server产生的估计值是否与实际执行计划中的实际行数相匹配。如果他们离得很远,SQL Server通常会做出不好的选择。因此,提供更好的统计信息可以帮助您查询性能。

+0

+1为实际行数和统计 –

1

我觉得排序发生了这个连接:

FROM custOrders c 
     INNER JOIN files f 
       ON c.orderid = f.orderid 

我会创建的文件,其中包括列的OrderID和statusid索引,因为查询也使用statusid列。

您可能还需要考虑以下几点变化:

  1. 你不需要“ac.adminuserid IS NOT NULL”,因为这是由内覆盖adminusers和admincustomers之间
  2. 变化加盟测试“f.statusid NOT IN(5,6)”为肯定条件(例如In),因为负面条件对于处理而言更昂贵。
+0

[文件]已经有一个覆盖索引 –

+0

是的,它已经在'Files'上做了非聚簇索引查找。有什么办法可以进一步减少来自'Files'的记录数? –

+0

从性能角度来看,非聚簇索引查找很好。减少记录计数的另一个改变是消除对状态ID的NOT IN检查,正如我上面推荐的那样。 –

2

SQL Server执行排序,使合并的数据集中到那种运营权,并在Orders表中的记录之间的连接。合并连接本身是连接数据集中所有记录的非常有效的方式,但它要求每个要连接的数据集按照连接键的顺序排序。

由于PK_Orders密钥已经订购了OrderID,因此SQL Server决定通过对连接的另一端(排序的右边的其他内容)进行排序以利用这两个数据集合并在一起在计划中的那一点。合并连接的常见替代方法是散列连接,但这不会对您有所帮助,因为您会改为使用昂贵的散列连接运算符而不是排序和合并。在这种情况下,查询优化器已确定排序和合并的效率更高。

计划中昂贵步骤的根本原因是需要将订单表中的所有记录合并到数据集中。有没有办法限制来自files表的记录?如果不在5,6中的记录少于总表格大小的10%,则files.statusid上的索引可能会有帮助。

QO认为大部分记录将在最后过滤掉。尝试将尽可能多的过滤条件推回到记录源,以便在计划中间处理更少的记录。

编辑:我忘了提及,有一个我们可以看看的执行计划是非常有帮助的。有没有什么办法可以让实际的执行计划结果看到通过这些操作员的记录的实际数量?有时候,估计的记录数可能会有点偏离。

编辑:展望深入到第二至最后一个过滤器运营商的上游领域,总结如下:

c.CustomerId=o.CustomerId 
OR o.CustomerId=cr.SecondaryCustomerId AND cr.SecondaryCustomerId IS NOT NULL 

看起来像SQL Server正在生产OrdersCustomers达之间的所有可能的匹配记录之间的交叉连接到此指向查询(第二个到最后一个过滤器运算符右侧的计划),然后查看每条记录的条件以确定它是否确实匹配。注意进入过滤器的线路是否真的很胖,线路是否很薄?这是因为在该运营商之后,估计的行数从21k到4。忘记我之前说过的话,这可能是计划中的主要问题。即使这些列上有索引,SQL Server也无法使用它们,因为连接条件太复杂。这导致计划将所有记录合并到一起,而不是仅仅寻找所需的记录,因为它无法立即使用完整连接谓词。

我的第一个想法是将CTE custOrders改为两个数据集的联合:一个使用CustomerId,另一个使用SecondaryCustomerId加入。这将重复CTE其余部分的工作,但如果它能够正确使用索引,这可能是一个巨大的胜利。

+0

好的,我更新了实际计划 –

+0

仍然看起来像原来的估计计划。您是在XML Playground上编辑问题还是更改文档? –

0

我知道这个问题是相当古老的,但我有这个相同的问题,并意识到有一个完全不同的原因,我的表突然减慢。症状是一样的,更新视图的速度很慢,以前闪电般快。 “排序”的成本为40%。 此解决方案可能对某人有用,而且很简单。 加入表格时,确保您加入“喜欢相似”的基础。 我加入了两张ID。但是在一个表中,我的ID被设置为int,另一个被设置为nvarchar。我纠正了这一点,让他们都被定义为相同的类型,并且视图恢复了闪电般的速度。

希望这可以帮助其他人避免花费一个星期的时间试图找出SQL的问题,当它真的是PEBKAC的时刻。

(问题键盘和椅子之间存在)

相关问题