2013-01-08 35 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的時刻。

(問題鍵盤和椅子之間存在)

相關問題