存储过程性能 Select SQL
Stored procedure performance Select SQL
我有以下 table:
CREATE TABLE [dbo].[_tbHRPro](
[ideID] [int] IDENTITY(-2147483648,1) NOT NULL,
[FID] [int] NULL,
[myDate] [datetime] NULL,
[myTime] [time](7) NULL,
[oValue] [decimal](18, 2) NULL,
[pValue] [decimal](18, 2) NULL,
CONSTRAINT [PK__tbHRPro] PRIMARY KEY CLUSTERED
(
[ideIDID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
然后,我有以下存储过程:
DECLARE @MonthID int = 2;
DECLARE @Year varchar(5) = '2014';
DECLARE @date1 DATE;
DECLARE @date2 DATE;
SET @date1 = DATEADD(DAY,-1,DATEADD(MONTH,1,CAST(CAST(@MonthID AS VARCHAR)+'/01/'+CAST(@Year AS VARCHAR)AS DATE)))
SET @date2 = CAST('01/01/'+CAST(@Year AS VARCHAR)AS DATE)
SELECT
a.ideID
, a.FID
, b.FC
, a.myDate
, a.myTime
, a.oValue
, a.pValue
INTO
#TEMPX
FROM
_tbHRPro a
INNER JOIN _FC b ON a.FID = b.FID
WHERE
myDate BETWEEN Dateadd(day, -1, @date2) AND dateadd(day, 1, @date1)
;WITH CTE AS
(
SELECT
T1.ideID
, T1.FID
, T1.FC
, T1.myDate
, T1.myTime
, T1.oValue
, CASE WHEN T1.oValue = 0 THEN 0 ELSE T1.oValue - T2.oValue END xValue
, T1.pValue
, CAST(T1.myDate AS datetime) + CAST(T1.myTime as datetime) oDateTime
, (CASE WHEN T1.oValue = 0 THEN 0 ELSE T1.oValue - T2.oValue END) - T1.pValue sDel
FROM
#TEMPX T1
LEFT JOIN #TEMPX T2 on T1.FID = T2.FID
AND DATEADD(HOUR, -1, CAST(T1.myDate AS datetime) + CAST(T1.myTime AS datetime)) = CAST(T2.myDate AS datetime) + CAST(T2.myTime AS datetime)
LEFT JOIN #TEMPX T3 on T1.FID = T3.FID
AND DATEADD(HOUR, 1, CAST(T1.myDate AS datetime) + CAST(T1.myTime AS datetime)) = CAST(T3.myDate AS datetime) + CAST(T3.myTime AS datetime)
)
, CTE2 AS
(
SELECT
T1.ideID
, T1.FID
, T1.FC
, T1.myDate
, T1.myTime
, T1.oValue
, CASE WHEN T1.oValue = 0 then (T2.xValue + T3.xValue) / 2 ELSE T1.xValue END AS xValue
, T1.pValue
, (CASE WHEN T1.oValue = 0 then (T2.xValue + T3.xValue) / 2 ELSE T1.xValue END) - T1.pValue sDel
FROM
CTE T1
LEFT JOIN CTE T2 ON T1.myDate = T2.myDate
AND T1.FID = T2.FID
AND DATEADD(HOUR, -1, T1.oDateTime)= T2.oDateTime
LEFT JOIN CTE T3 on T1.myDate = T3.myDate and T1.FID = T3.FID
AND DATEADD(HOUR, 1, T1.oDateTime)= T3.oDateTime
)
SELECT
ideID
, FID
, FC
, myDate
, myTime
, oValue
, xValue
, pValue
, sDel
INTO
#_vwHRPro
FROM
CTE2
ORDER BY
FC
, myDate
, myTime
;WITH ff AS
(
SELECT
FID
, FC
, DATEADD(hh, - 1, DATEADD(hh, DATEPART(hh, myTime), myDate)) AS newDate
, xValue
FROM
#_vwHRPro
)
SELECT
A.FID1
, A.FC1
, A.myDate1
, A.totxValue1
, B.FID2
, B.FC2
, B.myDate2
, B.totxValue2
, C.FID3
, C.FC3
, C.myDate3
, C.totxValue3
INTO
#_vwpm102
FROM
(
SELECT
FID AS FID1
, FC AS FC1
, CAST(newDate AS DATE) AS myDate1
, SUM(xValue) AS totxValue1
FROM
ff
WHERE
(FC LIKE '%1%')
GROUP BY
FID
, FC
, CAST(newDate AS DATE)
) AS A FULL OUTER JOIN
(
SELECT
FID AS FID2
, FC AS FC2
, CAST(newDate AS DATE) AS myDate2
, SUM(xValue) AS totxValue2
FROM
ff
WHERE
(FC LIKE '%2%')
GROUP BY
FID
, FC
, CAST(newDate AS DATE)
) AS B ON A.myDate1 = B.myDate2
FULL OUTER JOIN
(
SELECT
FID AS FID3
, FC AS FC3
, CAST(newDate AS DATE) AS myDate3
, SUM(xValue) AS totxValue3
FROM
ff
WHERE
(FC LIKE '%3%')
GROUP BY
FID
, FC
, CAST(newDate AS DATE)
) AS C ON A.myDate1 = C.myDate3
SELECT * FROM #_vwpm102 order by FC1, myDate1
我使用临时 table 来减少数据的加载时间。数据量很大,从2001年开始运行
我执行存储过程的加载时间是32秒
我尝试从查询 windows 运行,它加载也大约 30 秒。但是因为它存储在临时table,所以我第二次运行。
我只需要select下面的语句:
SELECT * FROM #_vwpm102 order by FC1, myDate1
加载速度如此之快,仅需 1 秒。
有谁知道如何最大限度地减少加载时间?至少,不到10秒。
感谢您的帮助和想法。干杯,
没有table模式和执行计划,人们只能猜测。
在您的查询中:
对 SP 进行一些更改
(1) Use recompilation sp to use statistics fullest.
(2) Don`t use function in where condition make a column in temp table and then join that column
(3) FC LIKE '%1%' and FC LIKE '%1%' is this really necessary avoid these kind of condition.
为了使 CTE 你有 "LEFT JOIN #TEMPX T3" 但从不使用 T3 - 删除它。有很多列被放入从未使用过的临时 tables - 杀死它们。
CAST() 很昂贵,您正在加入它们。我会在 _tbHRPro table.
中添加一个计算列
ALTER TABLE _tbHRPro
Add Column myDateTime As CAST(myDate AS datetime) + CAST(myTime as datetime)
(我打赌你也会用它做很多其他事情。)
然后在此计算列上添加索引:
CREATE INDEX IDX_tbHRPro_myDateTime ON _tbHRPro(myDateTime)
这会大大加快速度。
而不是将列命名为 FC1、FC2、FC3、myDate1、myDate2 等。我将使用一个名为 FCType 的列(也许将其设为 _FC table 上的计算列)
ALTER TABLE _FC
Add Column FCType AS CASE WHEN FC LIKE '%1%' THEN 1
CASE WHEN FC LIKE '%2%' THEN 2
CASE WHEN FC LIKE '%3%' THEN 3 END
那你以后就可以分组了。
那么我认为你可以将 SQL 简化为:
;WITH CTE AS
(
SELECT
me.ideID
,me.FID
,me.myDateTime
,CASE WHEN me.oValue = 0 or me.oValue - behind.oValue = 0
THEN
(CASE WHEN behind.oValue = 0
THEN 0
ELSE behind.oValue - behind2.oValue END +
CASE WHEN infront.oValue = 0
THEN 0
ELSE me.oValue - infront.oValue END) END / 2
ELSE .oValue - T2.oValue END xValue
FROM _tbHRPro me
LEFT JOIN _tbHRPro behind on me.FID = behind.FID
AND DATEADD(HOUR, -1, me.myDateTime) = behind.myDateTime
LEFT JOIN _tbHRPro behind2 on me.FID = behind2.FID
AND DATEADD(HOUR, -2, me.myDateTime) = behind2.myDateTime
LEFT JOIN _tbHRPro infront on me.FID = infront.FID
AND DATEADD(HOUR, 1, me.myDateTime) = infront.myDateTime
WHERE me.myDate
BETWEEN Dateadd(day, -1, @date2) AND dateadd(day, 1, @date1)
)
然后从中生成结果集:
select cast(CTE.myDateTime as Date) theDate,
_FC.FCType,
_FC.FC,
SUM(CTE.xValue) AS totxValue
from CTE
inner join _FC
ON CTE.FID = _FC.FID
GROUP BY cast(CTE.myDateTime as Date)
,_FC.FCType
,_FC.FC
不太确定 xValue 的正确计算是什么,但您明白了。而且我没有做一些细节,比如请假一个小时来制作 myDate1。
我有以下 table:
CREATE TABLE [dbo].[_tbHRPro](
[ideID] [int] IDENTITY(-2147483648,1) NOT NULL,
[FID] [int] NULL,
[myDate] [datetime] NULL,
[myTime] [time](7) NULL,
[oValue] [decimal](18, 2) NULL,
[pValue] [decimal](18, 2) NULL,
CONSTRAINT [PK__tbHRPro] PRIMARY KEY CLUSTERED
(
[ideIDID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
然后,我有以下存储过程:
DECLARE @MonthID int = 2;
DECLARE @Year varchar(5) = '2014';
DECLARE @date1 DATE;
DECLARE @date2 DATE;
SET @date1 = DATEADD(DAY,-1,DATEADD(MONTH,1,CAST(CAST(@MonthID AS VARCHAR)+'/01/'+CAST(@Year AS VARCHAR)AS DATE)))
SET @date2 = CAST('01/01/'+CAST(@Year AS VARCHAR)AS DATE)
SELECT
a.ideID
, a.FID
, b.FC
, a.myDate
, a.myTime
, a.oValue
, a.pValue
INTO
#TEMPX
FROM
_tbHRPro a
INNER JOIN _FC b ON a.FID = b.FID
WHERE
myDate BETWEEN Dateadd(day, -1, @date2) AND dateadd(day, 1, @date1)
;WITH CTE AS
(
SELECT
T1.ideID
, T1.FID
, T1.FC
, T1.myDate
, T1.myTime
, T1.oValue
, CASE WHEN T1.oValue = 0 THEN 0 ELSE T1.oValue - T2.oValue END xValue
, T1.pValue
, CAST(T1.myDate AS datetime) + CAST(T1.myTime as datetime) oDateTime
, (CASE WHEN T1.oValue = 0 THEN 0 ELSE T1.oValue - T2.oValue END) - T1.pValue sDel
FROM
#TEMPX T1
LEFT JOIN #TEMPX T2 on T1.FID = T2.FID
AND DATEADD(HOUR, -1, CAST(T1.myDate AS datetime) + CAST(T1.myTime AS datetime)) = CAST(T2.myDate AS datetime) + CAST(T2.myTime AS datetime)
LEFT JOIN #TEMPX T3 on T1.FID = T3.FID
AND DATEADD(HOUR, 1, CAST(T1.myDate AS datetime) + CAST(T1.myTime AS datetime)) = CAST(T3.myDate AS datetime) + CAST(T3.myTime AS datetime)
)
, CTE2 AS
(
SELECT
T1.ideID
, T1.FID
, T1.FC
, T1.myDate
, T1.myTime
, T1.oValue
, CASE WHEN T1.oValue = 0 then (T2.xValue + T3.xValue) / 2 ELSE T1.xValue END AS xValue
, T1.pValue
, (CASE WHEN T1.oValue = 0 then (T2.xValue + T3.xValue) / 2 ELSE T1.xValue END) - T1.pValue sDel
FROM
CTE T1
LEFT JOIN CTE T2 ON T1.myDate = T2.myDate
AND T1.FID = T2.FID
AND DATEADD(HOUR, -1, T1.oDateTime)= T2.oDateTime
LEFT JOIN CTE T3 on T1.myDate = T3.myDate and T1.FID = T3.FID
AND DATEADD(HOUR, 1, T1.oDateTime)= T3.oDateTime
)
SELECT
ideID
, FID
, FC
, myDate
, myTime
, oValue
, xValue
, pValue
, sDel
INTO
#_vwHRPro
FROM
CTE2
ORDER BY
FC
, myDate
, myTime
;WITH ff AS
(
SELECT
FID
, FC
, DATEADD(hh, - 1, DATEADD(hh, DATEPART(hh, myTime), myDate)) AS newDate
, xValue
FROM
#_vwHRPro
)
SELECT
A.FID1
, A.FC1
, A.myDate1
, A.totxValue1
, B.FID2
, B.FC2
, B.myDate2
, B.totxValue2
, C.FID3
, C.FC3
, C.myDate3
, C.totxValue3
INTO
#_vwpm102
FROM
(
SELECT
FID AS FID1
, FC AS FC1
, CAST(newDate AS DATE) AS myDate1
, SUM(xValue) AS totxValue1
FROM
ff
WHERE
(FC LIKE '%1%')
GROUP BY
FID
, FC
, CAST(newDate AS DATE)
) AS A FULL OUTER JOIN
(
SELECT
FID AS FID2
, FC AS FC2
, CAST(newDate AS DATE) AS myDate2
, SUM(xValue) AS totxValue2
FROM
ff
WHERE
(FC LIKE '%2%')
GROUP BY
FID
, FC
, CAST(newDate AS DATE)
) AS B ON A.myDate1 = B.myDate2
FULL OUTER JOIN
(
SELECT
FID AS FID3
, FC AS FC3
, CAST(newDate AS DATE) AS myDate3
, SUM(xValue) AS totxValue3
FROM
ff
WHERE
(FC LIKE '%3%')
GROUP BY
FID
, FC
, CAST(newDate AS DATE)
) AS C ON A.myDate1 = C.myDate3
SELECT * FROM #_vwpm102 order by FC1, myDate1
我使用临时 table 来减少数据的加载时间。数据量很大,从2001年开始运行
我执行存储过程的加载时间是32秒
我尝试从查询 windows 运行,它加载也大约 30 秒。但是因为它存储在临时table,所以我第二次运行。
我只需要select下面的语句:
SELECT * FROM #_vwpm102 order by FC1, myDate1
加载速度如此之快,仅需 1 秒。
有谁知道如何最大限度地减少加载时间?至少,不到10秒。
感谢您的帮助和想法。干杯,
没有table模式和执行计划,人们只能猜测。 在您的查询中: 对 SP 进行一些更改
(1) Use recompilation sp to use statistics fullest.
(2) Don`t use function in where condition make a column in temp table and then join that column
(3) FC LIKE '%1%' and FC LIKE '%1%' is this really necessary avoid these kind of condition.
为了使 CTE 你有 "LEFT JOIN #TEMPX T3" 但从不使用 T3 - 删除它。有很多列被放入从未使用过的临时 tables - 杀死它们。
CAST() 很昂贵,您正在加入它们。我会在 _tbHRPro table.
中添加一个计算列ALTER TABLE _tbHRPro
Add Column myDateTime As CAST(myDate AS datetime) + CAST(myTime as datetime)
(我打赌你也会用它做很多其他事情。)
然后在此计算列上添加索引:
CREATE INDEX IDX_tbHRPro_myDateTime ON _tbHRPro(myDateTime)
这会大大加快速度。
而不是将列命名为 FC1、FC2、FC3、myDate1、myDate2 等。我将使用一个名为 FCType 的列(也许将其设为 _FC table 上的计算列)
ALTER TABLE _FC
Add Column FCType AS CASE WHEN FC LIKE '%1%' THEN 1
CASE WHEN FC LIKE '%2%' THEN 2
CASE WHEN FC LIKE '%3%' THEN 3 END
那你以后就可以分组了。
那么我认为你可以将 SQL 简化为:
;WITH CTE AS
(
SELECT
me.ideID
,me.FID
,me.myDateTime
,CASE WHEN me.oValue = 0 or me.oValue - behind.oValue = 0
THEN
(CASE WHEN behind.oValue = 0
THEN 0
ELSE behind.oValue - behind2.oValue END +
CASE WHEN infront.oValue = 0
THEN 0
ELSE me.oValue - infront.oValue END) END / 2
ELSE .oValue - T2.oValue END xValue
FROM _tbHRPro me
LEFT JOIN _tbHRPro behind on me.FID = behind.FID
AND DATEADD(HOUR, -1, me.myDateTime) = behind.myDateTime
LEFT JOIN _tbHRPro behind2 on me.FID = behind2.FID
AND DATEADD(HOUR, -2, me.myDateTime) = behind2.myDateTime
LEFT JOIN _tbHRPro infront on me.FID = infront.FID
AND DATEADD(HOUR, 1, me.myDateTime) = infront.myDateTime
WHERE me.myDate
BETWEEN Dateadd(day, -1, @date2) AND dateadd(day, 1, @date1)
)
然后从中生成结果集:
select cast(CTE.myDateTime as Date) theDate,
_FC.FCType,
_FC.FC,
SUM(CTE.xValue) AS totxValue
from CTE
inner join _FC
ON CTE.FID = _FC.FID
GROUP BY cast(CTE.myDateTime as Date)
,_FC.FCType
,_FC.FC
不太确定 xValue 的正确计算是什么,但您明白了。而且我没有做一些细节,比如请假一个小时来制作 myDate1。