我正在研究時間表管理的Web應用程序。我編寫了一個查詢,按周將員工的所有時間輸入分組。而且我也必須使用分頁。查詢速度已經很慢,例如數據庫中有10個條目,它需要2-3秒才能運行。SQL Server時間表查詢性能
查詢使用兩個表。 TimeEntry代表一個工作日,當員工開始工作,完成工作並暫停時(TimeEntry.Pause)。
我用這個表按星期分組,我按天計算(星期一,星期二等) TimeType只是一種小時。
第二個表格代表公司在給定的一週內爲員工支付多少時間。
只有PK被索引。
在第二圖像,你可以在這裏看到的結果列:
FirstDayOfTheWeek
LastDayOftheWeek
SumByDayWeek每個
HT給予總工作時間本週
惠普給他多少小時已付
HB給他多少小時在是時間銀行本週
HB TOT。給他多少小時在是時間銀行,直到開始
我想有一些提示,以儘可能多的優化這個查詢越好!
這裏是SQL模式:
下面是結果的一個例子:
result http://s12.postimg.org/gbwc1wiqz/image.png
這裏是執行計劃:
ALTER PROCEDURE [dbo].[TimesheetWeek_Employee_Search]
@pPageNumber int,
@pEmployeeID int
AS
BEGIN
SET XACT_ABORT ON
SET NOCOUNT ON
DECLARE @Count int
DECLARE @PageCount int
DECLARE @TmpTimesheetWeekEmployee TABLE(FirstDayOfWeek DateTime, CCQPaidHour int, CCQPaidMinute int, STAFFPaidHour int, STAFFPaidMinute int,
CCQAdjustementHour int, CCQAdjustementMinute int, STAFFAdjustementHour int, STAFFAdjustementMinute int)
Insert into @TmpTimesheetWeekEmployee(FirstDayOfWeek, CCQPaidHour, CCQPaidMinute, STAFFPaidHour, STAFFPaidMinute,
CCQAdjustementHour, CCQAdjustementMinute, STAFFAdjustementHour, STAFFAdjustementMinute)
select FirstDayOfWeek, CCQPaidHour, CCQPaidMinute, STAFFPaidHour, STAFFPaidMinute,
CCQAdjustementHour, CCQAdjustementMinute, STAFFAdjustementHour, STAFFAdjustementMinute
from TimesheetWeekEmployee
where EmployeeID = @pEmployeeID
DECLARE @TmpTimeEntry TABLE(ID int, TimesheetID int, StartTime DateTime, EndTime DateTime, [Pause] int, TimeTypeID int)
Insert into @TmpTimeEntry(ID, TimesheetID, StartTime, EndTime, [Pause], TimeTypeID)
select ID, TimesheetID, StartTime, EndTime, [Pause], TimeTypeID
from TimeEntry
where EmployeeID = @pEmployeeID
select @Count = (select count(*) from (select 1 C
from @TmpTimeEntry TimeEntry
group by dbo.FirstDayOfWeek(StartTime), dbo.LastDayOfWeek(StartTime)) TE);
select @PageCount = (case when @Count % 10 = 0 then @Count/10
when @Count < 10 then 1
else @Count/10 + 1 end)
select eID, CONVERT(char(10), TSW.FirstDayOfWeek ,126)FirstDayOfWeek, LastDayOfWeek,
MinuteCCQ, LundiCCQ, MardiCCQ, MercrediCCQ, JeudiCCQ, VendrediCCQ, SamediCCQ,
sum(coalesce(TotalCCQ,0)) TotalCCQBefore,
MinuteSTAFF, LundiSTAFF, MardiSTAFF, MercrediSTAFF, JeudiSTAFF, VendrediSTAFF, SamediSTAFF,
sum(coalesce(TotalSTAFF,0)) TotalSTAFFBefore,
@pEmployeeID EmployeeID,
@PageCount 'PageCount',
coalesce(TWET.TotalCCQPaid, 0) 'TotalCCQPaid',
coalesce(Twet.TotalSTAFFPaid, 0) 'TotalSTAFFPaid',
coalesce(TWE.CCQPaid, 0) CCQPaid,
coalesce(TWE.STAFFPaid, 0) STAFFPaid
from (select dbo.Encrypt(ROW_NUMBER() over(order by dbo.FirstDayOfWeek(StartTime) desc)) as 'eID',
dbo.FirstDayOfWeek(StartTime) FirstDayOfWeek,
CONVERT(char(10),dbo.LastDayOfWeek(StartTime) ,126) LastDayOfWeek,
Sum(case when TimeTypeID = 3 then DATEDIFF(mi,StartTime,EndTime) - Pause else 0 end) 'MinuteCCQ',
Sum((case when DATEPART(dw,StartTime) = 1 and TimeTypeID = 3 then (DATEDIFF(mi,StartTime,EndTime) - Pause) else 0 end)) 'LundiCCQ',
Sum((case when DATEPART(dw,StartTime) = 2 and TimeTypeID = 3 then (DATEDIFF(mi,StartTime,EndTime) - Pause) else 0 end)) 'MardiCCQ',
Sum((case when DATEPART(dw,StartTime) = 3 and TimeTypeID = 3 then (DATEDIFF(mi,StartTime,EndTime) - Pause) else 0 end)) 'MercrediCCQ',
Sum((case when DATEPART(dw,StartTime) = 4 and TimeTypeID = 3 then (DATEDIFF(mi,StartTime,EndTime) - Pause) else 0 end)) 'JeudiCCQ',
Sum((case when DATEPART(dw,StartTime) = 5 and TimeTypeID = 3 then (DATEDIFF(mi,StartTime,EndTime) - Pause) else 0 end)) 'VendrediCCQ',
Sum((case when DATEPART(dw,StartTime) = 6 and TimeTypeID = 3 then (DATEDIFF(mi,StartTime,EndTime) - Pause) else 0 end)) 'SamediCCQ',
Sum(case when TimeTypeID = 4 then DATEDIFF(mi,StartTime,EndTime) - Pause else 0 end) 'MinuteSTAFF',
Sum((case when DATEPART(dw,StartTime) = 1 and TimeTypeID = 4 then (DATEDIFF(mi,StartTime,EndTime) - Pause) else 0 end)) 'LundiSTAFF',
Sum((case when DATEPART(dw,StartTime) = 2 and TimeTypeID = 4 then (DATEDIFF(mi,StartTime,EndTime) - Pause) else 0 end)) 'MardiSTAFF',
Sum((case when DATEPART(dw,StartTime) = 3 and TimeTypeID = 4 then (DATEDIFF(mi,StartTime,EndTime) - Pause) else 0 end)) 'MercrediSTAFF',
Sum((case when DATEPART(dw,StartTime) = 4 and TimeTypeID = 4 then (DATEDIFF(mi,StartTime,EndTime) - Pause) else 0 end)) 'JeudiSTAFF',
Sum((case when DATEPART(dw,StartTime) = 5 and TimeTypeID = 4 then (DATEDIFF(mi,StartTime,EndTime) - Pause) else 0 end)) 'VendrediSTAFF',
Sum((case when DATEPART(dw,StartTime) = 6 and TimeTypeID = 4 then (DATEDIFF(mi,StartTime,EndTime) - Pause) else 0 end)) 'SamediSTAFF'
from @TmpTimeEntry TimeEntry
group by dbo.FirstDayOfWeek(StartTime), dbo.LastDayOfWeek(StartTime)) TSW
left join ( select dbo.FirstDayOfWeek(StartTime) FirstDayOfWeek,
Sum((case when TimeTypeID = 3 then (DATEDIFF(mi,StartTime,EndTime) - [Pause]) else 0 end)) 'TotalCCQ',
Sum((case when TimeTypeID = 4 then (DATEDIFF(mi,StartTime,EndTime) - [Pause]) else 0 end)) 'TotalSTAFF'
from @TmpTimeEntry TimeEntry
group by dbo.FirstDayOfWeek(StartTime), dbo.LastDayOfWeek(StartTime)) TT
on TT.FirstDayOfWeek < TSW.FirstDayOfWeek
left join (select E.FirstDayOfWeek,
sum(coalesce(twe.CCQPaidHour,0)* 60 + coalesce(twe.CCQPaidMinute,0)-(coalesce(twe.CCQAdjustementHour,0)* 60 + coalesce(twe.CCQAdjustementMinute,0))) 'TotalCCQPaid',
sum(coalesce(twe.STAFFPaidHour,0) * 60 + coalesce(twe.STAFFPaidMinute,0)-(coalesce(twe.STAFFAdjustementHour,0) * 60 + coalesce(twe.STAFFAdjustementMinute,0))) 'TotalSTAFFPaid'
from (select dbo.FirstDayOfWeek(StartTime) FirstDayOfWeek,
EmployeeID
from TimeEntry
where EmployeeID = @pEmployeeID
group by dbo.FirstDayOfWeek(StartTime), EmployeeID) E
left join @TmpTimesheetWeekEmployee twe on twe.FirstDayOfWeek < e.FirstDayOfWeek
group by E.FirstDayOfWeek) as TWET
on TWET.FirstDayOfWeek = TSW.FirstDayOfWeek
left join (select FirstDayOfWeek,
coalesce(CCQPaidHour,0)* 60 + coalesce(CCQPaidMinute,0) 'CCQPaid',
coalesce(STAFFPaidHour,0) * 60 + coalesce(STAFFPaidMinute,0) 'STAFFPaid'
from @TmpTimesheetWeekEmployee) as TWE
on dbo.FirstDayOfWeek(TWE.FirstDayOfWeek) = TSW.FirstDayOfWeek
GROUP BY TSW.FirstDayOfWeek, LastDayOfWeek, eID,
MinuteCCQ, LundiCCQ, MardiCCQ, MercrediCCQ, JeudiCCQ, VendrediCCQ, SamediCCQ,
MinuteSTAFF, LundiSTAFF, MardiSTAFF, MercrediSTAFF, JeudiSTAFF, VendrediSTAFF, SamediSTAFF, MinuteSTAFF,
CCQPaid, STAFFPaid, TotalCCQPaid, TotalSTAFFPaid
ORDER BY TSW.FirstDayOfWeek desc
OFFSET (case when @pPageNumber > @PageCount then 1
else (@pPageNumber -1) * 10 end) ROWS
FETCH NEXT 10 ROWS ONLY
END
執行計劃和信息和現有的索引將是解決您的問題最有幫助的事情。 – 2015-04-01 01:11:19
這可能會更好地服務於dba.stackexchange.com – NotMe 2015-04-01 01:22:03
我添加一個鏈接來下載執行計劃。唯一的索引列是PK。我將嘗試在dba.stackechange.com上發佈我的問題 – 2015-04-01 01:29:27