我有一段存儲過程,我寫回來幫助生成將用於與外部資源共享數據的XML文件。基本上,最終用戶在名爲DataSharing的表內轉儲數據,然後當我們執行查詢時,它將返回一個XML文檔,其中包含DataSharing中指定的必需字段。現在這個過程確實很好,但速度非常慢。當我通過SSMS運行它並設置'顯示實際執行計劃'時,94%的查詢花費在索引假脫機(eager spool)上。經過研究,它看起來像我應該重做查詢以更好地執行。SQL索引假脫機(eager spool)加速查詢
由於數據列我永遠不知道他們是什麼,我必須做獨特的樞軸爲了生成我的數據。
下面是該過程:
CREATE PROCEDURE [dbo].[sp_HPSDDataSharing]
-- Add the parameters for the stored procedure here
@fileName varchar(MAX), @StartDate datetime, @EndDate datetime
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE @sqlCommand varchar(MAX), @listStr VARCHAR(MAX)
SELECT @listStr =
COALESCE(@listStr +',' ,'') + '[' + [ColumnName] + ']'
FROM [FCPP_HPSD].[dbo].[DataSharing]
WHERE FileName = @fileName
DECLARE @Result XML
SET @sqlCommand = 'Select * From (SELECT
[DatapointDate]
,dp.ColumnName
,[DataPointValue]
FROM [FCPP_HPSD].[dbo].[vw_DataCollection] DC
JOIN [FCPP_HPSD].[dbo].[Datasharing] dp
ON DC.DataPointID = DP.DatapointID
WHERE
[DatapointDate] >= ''' + CONVERT(varchar(MAX), @StartDate) + '''
and [DatapointDate] < ''' + CONVERT(varchar(MAX), @EndDate) + '''
and dc.DataPointID in (SELECT [DatapointID] FROM [FCPP_HPSD].[dbo].[DataSharing] Where FileName = ''' + @fileName + ''')
) AS source
PIVOT
(
SUM(DataPointValue)
FOR ColumnName IN ('+ @listStr +')
) as pvt
ORDER BY DatapointDate
FOR XML Path(''' + 'DataRow' + '''), ROOT;'
Print @sqlCommand
EXEC (@sqlCommand)
END
GO
完全執行的查詢看起來是這樣的:
SELECT *
FROM (SELECT [datapointdate],
dp.columnname,
[datapointvalue]
FROM [FCPP_HPSD].[dbo].[vw_datacollection] DC
JOIN [FCPP_HPSD].[dbo].[datasharing] dp
ON DC.datapointid = DP.datapointid
WHERE [datapointdate] >= 'Jul 15 2013 12:00AM'
AND [datapointdate] < 'Jul 22 2013 12:00AM'
AND dc.datapointid IN (SELECT [datapointid]
FROM [FCPP_HPSD].[dbo].[datasharing]
WHERE filename = 'fdrD3')) AS source
PIVOT (Sum(datapointvalue)
FOR columnname IN ([fdrD3_kWh_A],
[fdrD3_kWh_B],
[fdrD3_kWh_C],
[fdrD3_kWh],
[fdrD3_I_A],
[fdrD3_I_B],
[fdrD3_I_C],
[fdrD3_I_N],
[fdrD3_V_A],
[fdrD3_V_B],
[fdrD3_V_C],
[fdrD3_V_A-B],
[fdrD3_V_B-C],
[fdrD3_kV_C-A],
[fdrD3_kW],
[fdrD3_kVA],
[fdrD3_kVAr],
[fdrD3_kW_A],
[fdrD3_kW_B],
[fdrD3_kW_C],
[fdrD3_kVA_A],
[fdrD3_kVA_B],
[fdrD3_kVA_C],
[fdrD3_kVAr_A],
[fdrD3_kVAr_B],
[fdrD3_kVAr_C],
[fdrD3_F],
[fdrD3_Iang_A],
[fdrD3_Iang_B],
[fdrD3_Iang_C],
[fdrD3_Iang_N],
[fdrD3_Vang_A],
[fdrD3_Vang_B],
[fdrD3_Vang_C],
[fdrD3_Vang_A-B],
[fdrD3_Vang_B-C],
[fdrD3_Vang_C-A],
[fdrD3_PF_A],
[fdrD3_PF_B],
[fdrD3_PF_C],
[fdrD3_PF],
[fdrD3_Pst_V_A],
[fdrD3_Pst_V_B],
[fdrD3_Pst_V_C],
[fdrD3_Plt_V_A],
[fdrD3_Plt_V_B],
[fdrD3_Plt_V_C],
[fdrD3_Vdev_A],
[fdrD3_Vdev_B],
[fdrD3_Vdev_C],
[fdrD3_Fdev],
[fdrD3_THD_I_A],
[fdrD3_THD_I_B],
[fdrD3_THD_I_C],
[fdrD3_THD_I_N],
[fdrD3_THD_V_A],
[fdrD3_THD_V_B],
[fdrD3_THD_V_C])) AS pvt
ORDER BY datapointdate
FOR xml path('DataRow'), root;
所以目前的程序目前需要35-65秒才能運行。當我處理超時時,我真的需要看到有關加快這個過程。如果任何人都可以幫我解決我能做的事情,以幫助加快速度,擺脫索引假脫機(假脫機)的這麼多時間,我將不勝感激。
編輯1:
我加了一個SQL Fiddle所以希望這有助於。
那麼一件小事不會將開始日期和結束日期轉換爲字符串並返回日期。 – Hogan
沒有一個很好的指示說明表如何看起來像什麼,他們有什麼指數(或沒有),他們是什麼數量,如果有外鍵關係等等......很少有人可以建議......如果可能的話,轉到SQLFiddle,確保構建所有相關的表和它們的索引等,然後在這裏複製代碼,這樣至少有一個機會你會得到一個有用的答案。 – deroby
@霍根我曾想過這件事。但是當我執行Pivot時,只需要大約6秒的時間來執行,這是非常好的,因爲我們有547k行數據。 –