我之前發佈過類似的內容,但現在我正在從一個不同的方向來處理這個問題,所以我提出了一個新問題。我希望這是好的。CTE加入時速度很慢
我一直在使用CTE創建基於父費用的費用總和。在SQL和細節可以看這裏:
CTE Index recommendations on multiple keyed table
我不認爲我缺少的CTE什麼,但是當我用數據的一大桌(350萬使用它我得到一個問題行)。
表tblChargeShare
包含我需要的一些其他信息,例如InvoiceID
,所以我將CTE放在視圖vwChargeShareSubCharges
中,並將它加入到表中。
查詢:
Select t.* from vwChargeShareSubCharges t
inner join
tblChargeShare s
on t.CustomerID = s.CustomerID
and t.MasterChargeID = s.ChargeID
Where s.ChargeID = 1291094
返回幾毫秒的結果。
查詢:
Select ChargeID from tblChargeShare Where InvoiceID = 1045854
返回1行:
1291094
但查詢:
Select t.* from vwChargeShareSubCharges t
inner join
tblChargeShare s
on t.CustomerID = s.CustomerID
and t.MasterChargeID = s.ChargeID
Where InvoiceID = 1045854
需要2-3分鐘才能運行。
我保存了執行計劃並將它們加載到SQL Sentry中。爲快速查詢樹看起來是這樣的:
從慢查詢的計劃是:
我試圖重建索引,貫穿優化顧問以及各種組合查詢的子查詢。只要聯接包含PK以外的任何內容,查詢就會很慢。
我也有類似的問題在這裏:
SQL Server Query time out depending on Where Clause
其中用函數來做子行,而不是一個CTE的summimg。這是使用CTE重寫以避免我現在遇到的同樣問題。我已經閱讀了答案中的答案,但我不明智 - 我閱讀了關於提示和參數的一些信息,但我無法完成工作。我曾經認爲使用CTE重寫會解決我的問題。在具有幾千行的tblCharge上運行時查詢速度很快。
測試兩個SQL 2008 R2和SQL 2012
編輯:
我都凝結着查詢到一個單一的聲明,但同樣的問題仍然存在:
WITH RCTE AS
(
SELECT ParentChargeId, s.ChargeID, 1 AS Lvl, ISNULL(TotalAmount, 0) as TotalAmount, ISNULL(s.TaxAmount, 0) as TaxAmount,
ISNULL(s.DiscountAmount, 0) as DiscountAmount, s.CustomerID, c.ChargeID as MasterChargeID
from tblCharge c inner join tblChargeShare s
on c.ChargeID = s.ChargeID Where s.ChargeShareStatusID < 3 and ParentChargeID is NULL
UNION ALL
SELECT c.ParentChargeID, c.ChargeID, Lvl+1 AS Lvl, ISNULL(s.TotalAmount, 0), ISNULL(s.TaxAmount, 0), ISNULL(s.DiscountAmount, 0) , s.CustomerID
, rc.MasterChargeID
from tblCharge c inner join tblChargeShare s
on c.ChargeID = s.ChargeID
INNER JOIN RCTE rc ON c.PArentChargeID = rc.ChargeID and s.CustomerID = rc.CustomerID Where s.ChargeShareStatusID < 3
)
Select MasterChargeID as ChargeID, rcte.CustomerID, Sum(rcte.TotalAmount) as TotalCharged, Sum(rcte.TaxAmount) as TotalTax, Sum(rcte.DiscountAmount) as TotalDiscount
from RCTE inner join tblChargeShare s on rcte.ChargeID = s.ChargeID and RCTE.CustomerID = s.CustomerID
Where InvoiceID = 1045854
Group by MasterChargeID, rcte.CustomerID
GO
編輯: 更多玩耍,我只是不明白這一點。
該查詢即時(2MS):
Select t.* from
vwChargeShareSubCharges t
Where t.MasterChargeID = 1291094
而這需要3分:
DECLARE @ChargeID int = 1291094
Select t.* from
vwChargeShareSubCharges t
Where t.MasterChargeID = @ChargeID
即使我把號堆在 「在」,查詢還是瞬間:
Where t.MasterChargeID in (1291090, 1291091, 1291092, 1291093, 1291094, 1291095, 1291096, 1291097, 1291098, 1291099, 129109)
編輯2:
我可以從頭開始使用這個例子中的數據複製這樣的:
我創建了一些虛擬數據複製的問題。它不是那麼顯著,因爲我只加了100,000行,但壞的執行計劃仍然發生(在SQLCMD模式下運行):
CREATE TABLE [tblChargeTest](
[ChargeID] [int] IDENTITY(1,1) NOT NULL,
[ParentChargeID] [int] NULL,
[TotalAmount] [money] NULL,
[TaxAmount] [money] NULL,
[DiscountAmount] [money] NULL,
[InvoiceID] [int] NULL,
CONSTRAINT [PK_tblChargeTest] PRIMARY KEY CLUSTERED
(
[ChargeID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
END
GO
Insert into tblChargeTest
(discountAmount, TotalAmount, TaxAmount)
Select ABS(CHECKSUM(NewId())) % 10, ABS(CHECKSUM(NewId())) % 100, ABS(CHECKSUM(NewId())) % 10
GO 100000
Update tblChargeTest
Set ParentChargeID = (ABS(CHECKSUM(NewId())) % 60000) + 20000
Where ChargeID = (ABS(CHECKSUM(NewId())) % 20000)
GO 5000
CREATE VIEW [vwChargeShareSubCharges] AS
WITH RCTE AS
(
SELECT ParentChargeId, ChargeID, 1 AS Lvl, ISNULL(TotalAmount, 0) as TotalAmount, ISNULL(TaxAmount, 0) as TaxAmount,
ISNULL(DiscountAmount, 0) as DiscountAmount, ChargeID as MasterChargeID
FROM tblChargeTest Where ParentChargeID is NULL
UNION ALL
SELECT rh.ParentChargeID, rh.ChargeID, Lvl+1 AS Lvl, ISNULL(rh.TotalAmount, 0), ISNULL(rh.TaxAmount, 0), ISNULL(rh.DiscountAmount, 0)
, rc.MasterChargeID
FROM tblChargeTest rh
INNER JOIN RCTE rc ON rh.PArentChargeID = rc.ChargeID --and rh.CustomerID = rc.CustomerID
)
Select MasterChargeID, ParentChargeID, ChargeID, TotalAmount, TaxAmount, DiscountAmount , Lvl
FROM RCTE r
GO
然後運行這兩個查詢:
--Slow Query:
Declare @ChargeID int = 60900
Select *
from [vwChargeShareSubCharges]
Where MasterChargeID = @ChargeID
--Fast Query:
Select *
from [vwChargeShareSubCharges]
Where MasterChargeID = 60900
只是快速的想法...如果你把你的查詢'從vwChargeShareSubCharges t'選擇噸。*,其實際TSQL定義替換視圖'vwChargeShareSubCharges',加入到其他表酌情和運行查詢,它有什麼更快? – DMason
完全相同,如果我粘貼在完整的CTE。 – Molloch