我正在研究时间表管理的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