執行計劃百分比加起來不是 100%
我指的是 SQL Server 查詢執行計劃來獲取查詢成本,然後通過查看計劃來優化所需的東西。
但單個查詢成本加起來超過 100%。
這是我的查詢:
DECLARE @date SMALLDATETIME SELECT Reffd AS NAME ,( SELECT ( ( SELECT count(*) FROM [cal_reg].[dbo].[customer] WHERE upper(Reffd) = upper(main.reffd) AND cast(DATE AS SMALLDATETIME) = @date ) + ( SELECT count(*) FROM [cal_reg].[dbo].[rep] WHERE upper(Reffd) = upper(main.Reffd) AND cast(DATE AS SMALLDATETIME) = @date ) ) ) AS Completed ,( SELECT ( ( SELECT count(*) FROM [cal_reg].[dbo].[customer] WHERE upper([call Attnd]) = upper(main.[Reffd]) AND cast(DATE AS SMALLDATETIME) = @date ) + ( SELECT count(*) FROM [cal_reg].[dbo].[rep] WHERE upper([Call Attnd]) = upper(main.reffd) AND cast(DATE AS SMALLDATETIME) = @date ) ) ) AS Attended ,( SELECT ( ( SELECT ( ( SELECT count(*) FROM [cal_reg].[dbo].[customer] WHERE upper(Reffd) = upper(main.reffd) AND cast(DATE AS SMALLDATETIME) = @date ) + ( SELECT count(*) FROM [cal_reg].[dbo].[rep] WHERE upper(Reffd) = upper(main.Reffd) AND cast(DATE AS SMALLDATETIME) = @date ) ) ) ) + ( SELECT ( ( SELECT count(*) FROM [cal_reg].[dbo].[customer] WHERE upper([call Attnd]) = upper(main.[Reffd]) AND cast(DATE AS SMALLDATETIME) = @date ) + ( SELECT count(*) FROM [cal_reg].[dbo].[rep] WHERE upper([Call Attnd]) = upper(main.reffd) AND cast(DATE AS SMALLDATETIME) = @date ) ) ) ) AS Total ,'' AS f6row ,'' AS f8row FROM [cal_reg].[dbo].[customer] AS main WHERE cast(DATE AS SMALLDATETIME) = @date AND upper(reffd) IN ( SELECT upper(shname) FROM common.dbo.Password_table ) GROUP BY reffd
為此,我總共得到了 104%,如下所示:
我的問題是有可能解決超過 100% 的成本錯誤,還是有其他方法可以告訴我查詢是否有效執行?
執行計劃中操作員成本的總和超過 100% 是一個已知錯誤,並且按設計關閉!
Microsoft 於 2010 年 11 月 17 日下午 5:28 發布
感謝您花時間送出此觀察和簡單的複制。您觀察到的奇怪的成本百分比值是查詢計劃的特定結構的產物,這有點令人困惑,但最終確實有意義。它們不會以任何方式對查詢的執行產生不利影響。
連接運算符有兩個孩子 - 表掃描。但是,伺服器希望不必執行第二次表掃描。這是因為它希望從第一個表掃描中找到滿足查詢的“存在”部分的行。因此,在計算以連接為根的子樹的總成本時,它不包括第二次表掃描的成本。然而,它仍然估計並報告第二次表掃描的成本,管理工具將其計算為總查詢成本的百分比,就好像它將被執行一樣。
當然,在這種情況下,有必要執行第二次表掃描,因為第一次是空的。但是,引擎在保守的假設下執行,即始終至少有一行(可能僅在編譯查詢後才添加)。
坎貝爾
SQL 開發
Aaron Bertrand 送出了一個類似的錯誤 - SSMS:執行計劃有時超過 100%
Microsoft 於 2008 年 5 月 28 日上午 11:58 發布
再次感謝您引起我們的注意。這種異常出現在“行目標”和連接運算符存在的情況下。行目標是指何時不需要子樹(可能是整個查詢)返回所有可能的行。這最常發生在查詢具有“top”子句時,儘管還有其他原因。出現異常是因為我們不希望執行 Concatenation 的第二個孩子(因為我們希望第一個孩子提供所有必需的行)。假設他們返回單行,這些額外的孩子需要付出代價。唯一的選擇是給他們 0 成本,這將修復異常但可能會造成其他混亂,並導致優化器不關心計劃 - 我們不想這樣做以防萬一他們被執行。
坎貝爾弗雷澤,SQL 開發。
如果您想了解計劃成本核算的工作原理,Paul White 將在此處盡其所能進行解釋。
來自查詢處理器團隊 -這個成本是多少?
提高性能的一般準則 -
- 有適當的索引和最新的統計數據。
- 僅獲取所需的數據以及相關列。
- 擁有適當的 schema.table 和適當的索引和數據類型
- 使用統計時間、IO 在您進行更改之前和之後來衡量增益。
- 從本網站的專家那裡獲得幫助/指導 :-)
這就是我使用SQL Sentry 的免費計劃資源管理器的原因
我不會擔心 100%
大數字就是大數字
很多重複,所以開始優化一個
這只是您查詢的一個子集
DECLARE @date SMALLDATETIME SELECT Reffd AS NAME , ( SELECT ( ( SELECT count(*) FROM [cal_reg].[dbo].[customer] WHERE upper(Reffd) = upper(main.reffd) AND cast(DATE AS SMALLDATETIME) = @date ) + ( SELECT count(*) FROM [cal_reg].[dbo].[rep] WHERE upper(Reffd) = upper(main.Reffd) AND cast(DATE AS SMALLDATETIME) = @date ) ) ) AS Completed FROM [cal_reg].[dbo].[customer] AS main WHERE cast(main.DATE AS SMALLDATETIME) = @date AND upper(main.reffd) IN ( SELECT upper(shname) FROM common.dbo.Password_table ) GROUP BY main.reffd
使用不區分大小寫的排序規則
如果這是一個字元欄位,完整的 DATETIME 將消除一些成本
,那麼這是一個問題,您應該修復數據
DECLARE @date DATETIME SELECT Reffd AS NAME , ( SELECT ( ( SELECT count(*) FROM [cal_reg].[dbo].[customer] WHERE Reffd = main.reffd AND DATE = @date ) + ( SELECT count(*) FROM [cal_reg].[dbo].[rep] WHERE Reffd = main.Reffd AND DATE = @date ) ) ) AS Completed FROM [cal_reg].[dbo].[customer] AS main JOIN common.dbo.Password_table pw on pw.shname = main.reffd WHERE main.DATE = @date GROUP BY main.reffd
這可以分解為連接
DECLARE @date DATETIME SELECT Reffd AS NAME , ( count(cusR.Reffd) + count(repR.Reffd) ) as AS Completed , ( count(cusA.[call Attnd]) + count(repA.[call Attnd]) ) as AS Attended , ( count(cusR.Reffd) + count(repR.Reffd) + count(cusA.[call Attnd]) + count(repA.[call Attnd]) ) as AS Total FROM [cal_reg].[dbo].[customer] AS main JOIN common.dbo.Password_table pw on pw.shname = main.reffd and main.DATE = @date left join [cal_reg].[dbo].[customer] [cusR] on cusR.Reffd = main.reffd and cusR.DATE = main.DATE left join [cal_reg].[dbo].[rep] as [repR] on repR.Reffd = main.Reffd and repR.DATE = main.DATE left join [cal_reg].[dbo].[customer] [cusA] on cusA.[call Attnd] = main.reffd and cusA.DATE = main.DATE left join [cal_reg].[dbo].[rep] as [repA] on repA.[call Attnd] = main.Reffd and repA.DATE = main.DATE GROUP BY main.reffd
如果您在所有 Reffd 和 Date 上都有索引,那麼這應該會快速吸煙
那些循環正在殺死它,
希望這將擺脫其中一些循環
這就像一個刀具廣告 - 但等等還有更多
SELECT Reffd AS NAME , ( count(cus.Reffd) + count(rep.Reffd) ) as AS Completed , ( count(cus.[call Attnd]) + count(rep.[call Attnd]) ) as AS Attended , ( count(cus.Reffd) + count(rep.Reffd) + count(cus.[call Attnd]) + count(rep.[call Attnd]) ) as AS Total FROM [cal_reg].[dbo].[customer] AS main JOIN common.dbo.Password_table pw on pw.shname = main.reffd and main.DATE = @date left join [cal_reg].[dbo].[customer] [cus] on main.reffd in (cus.Reffd, cus.[call Attnd]) and cus.DATE = main.DATE left join [cal_reg].[dbo].[rep] as [rep] on main.Reffd in (rep.Reffd, rep.[call Attnd]) and rep.DATE = main.DATE GROUP BY main.reffd