Zan*_*ane 5 sql-server-2008 sql-server stored-procedures view
好的,所以我有一个运行非常缓慢的报告存储过程。客户抱怨报告无法运行,所以我开始调查问题在存储过程中的确切位置,我发现这部分占用了 99.8% 的时间。
DECLARE @xmlTemp TABLE (
CompanyID INT,
StoreID INT,
StartDate DATETIME,
DateStaID INT,
EndDate DATETIME,
DateEndID INT,
LastUpdate DATETIME)
INSERT INTO @xmlTemp
VALUES (50,
2,
'3/3/2013',
0,
'3/3/2013',
0,
'3/3/2013')
SELECT DISTINCT T.CompanyID,
CompanyName,
Z.StoreID,
StoreName,
CashedOutBy,
TransactionID,
RegisterID,
BusinessDate,
CashedOut,
Total - Isnull((SELECT Sum(DISTINCT PaymentAmount)
FROM vPullDrawerPayments
WHERE CompanyID = T.CompanyID
AND StoreID = T.StoreID
AND TransactionID = T.TransactionID
AND Isnull(PaymentType, 1) <> 1), 0) AS PaymentAmount,
'Cash' AS PaymentDesc,
CASE
WHEN Z.EndDate >= Z.LastUpdate THEN 1
ELSE 0
END AS MissingData
FROM vPullDrawerPayments AS T
INNER JOIN @xmlTemp AS Z
ON T.CompanyID = Z.CompanyID
AND T.StoreID = Z.StoreID
WHERE BusinessDate BETWEEN Z.StartDate AND Z.EndDate
UNION ALL
SELECT DISTINCT NC.CompanyID,
CompanyName,
Z.StoreID,
StoreName,
CashedOutBy,
TransactionID,
RegisterID,
BusinessDate,
CashedOut,
PaymentAmount,
PaymentDesc,
CASE
WHEN Z.EndDate >= Z.LastUpdate THEN 1
ELSE 0
END AS MissingData
FROM vPullDrawerPayments AS NC
INNER JOIN @xmlTemp AS Z
ON NC.CompanyID = Z.CompanyID
AND NC.StoreID = Z.StoreID
WHERE BusinessDate BETWEEN Z.StartDate AND Z.EndDate
AND Isnull(PaymentType, 1) <> 1
UNION ALL
SELECT DISTINCT C.CompanyID,
CompanyName,
Z.StoreID,
StoreName,
CashedOutBy,
TransactionID,
RegisterID,
BusinessDate,
CashedOut,
Sum(Abs(LineAmount)) AS PaymentAmount,
'Coupons' AS PaymentDesc,
CASE
WHEN Max(Z.EndDate) >= Max(Z.LastUpdate) THEN 1
ELSE 0
END AS MissingData
FROM vPullDrawerPayments AS C
INNER JOIN @xmlTemp AS Z
ON C.CompanyID = Z.CompanyID
AND C.StoreID = Z.StoreID
WHERE BusinessDate BETWEEN Z.StartDate AND Z.EndDate
GROUP BY C.CompanyID,
CompanyName,
Z.StoreID,
StoreName,
CashedOutBy,
TransactionID,
RegisterID,
BusinessDate,
CashedOut
Run Code Online (Sandbox Code Playgroud)
此查询的@xmlTemp 部分通常用于从我们的 Web 应用程序中获取参数,并将它们转换为报表可以实际使用的参数。为了测试这一点,我只是插入了为一家商店运行一天的值。运行此部分可能需要 20 分钟以上。
所以我通过PlanExplorer运行这个查询计划,看到它从我的两个事实表中提取所有数据,而不是只过滤掉那个商店和那天。如下图所示。
显然这是不好的。因此,我采取的下一步是删除 @xml temp 的连接,然后手动将值放入查询
WHERE
子句中,以查看效果如何。
SELECT DISTINCT T.CompanyID,
CompanyName,
T.StoreID,
StoreName,
CashedOutBy,
TransactionID,
RegisterID,
BusinessDate,
CashedOut,
Total - Isnull((SELECT Sum(DISTINCT PaymentAmount)
FROM vPullDrawerPayments
WHERE CompanyID = T.CompanyID
AND StoreID = T.StoreID
AND TransactionID = T.TransactionID
AND Isnull(PaymentType, 1) <> 1), 0) AS PaymentAmount,
'Cash' AS PaymentDesc
--CASE WHEN Z.'3/3/2013' >= Z.LastUpdate THEN 1 ELSE 0 END AS MissingData
FROM vPullDrawerPayments AS T
WHERE CompanyID = 50
AND StoreID = 1
AND BusinessDate BETWEEN '3/3/2013' AND '3/3/2013'
UNION ALL
SELECT DISTINCT NC.CompanyID,
CompanyName,
NC.StoreID,
StoreName,
CashedOutBy,
TransactionID,
RegisterID,
BusinessDate,
CashedOut,
PaymentAmount,
PaymentDesc
--CASE WHEN Z.'3/3/2013' >= Z.LastUpdate THEN 1 ELSE 0 END AS MissingData
FROM vPullDrawerPayments AS NC
WHERE CompanyID = 50
AND StoreID = 1
AND BusinessDate BETWEEN '3/3/2013' AND '3/3/2013'
AND Isnull(PaymentType, 1) <> 1
UNION ALL
SELECT DISTINCT C.CompanyID,
CompanyName,
C.StoreID,
StoreName,
CashedOutBy,
TransactionID,
RegisterID,
BusinessDate,
CashedOut,
Sum(Abs(LineAmount)) AS PaymentAmount,
'Coupons' AS PaymentDesc
--CASE WHEN MAX(Z.'3/3/2013') >= MAX(Z.LastUpdate) THEN 1 ELSE 0 END AS MissingData
FROM vPullDrawerPayments AS C
WHERE CompanyID = 50
AND StoreID = 1
AND BusinessDate BETWEEN '3/3/2013' AND '3/3/2013'
GROUP BY C.CompanyID,
CompanyName,
C.StoreID,
StoreName,
CashedOutBy,
TransactionID,
RegisterID,
BusinessDate,
CashedOut
Run Code Online (Sandbox Code Playgroud)
通过将其更改为简单的 where 子句,它会在 4 秒内运行,而不是 20 分钟及以上。查询计划也显示正确 有什么理由我应该看到这种行为吗?
在这里编辑是QueryPlan的完整链接。
[从我在 SQLPerformance.com 上的回答中复制。]
来自其他地方的讨论的一些非常简短的初步建议:
归档时间: |
|
查看次数: |
5530 次 |
最近记录: |