3张桌子
在WorkRecordFact中按位置查找数据的查询要花费很长时间。基本样本查询
SELECT workrecordfact.*
FROM workrecordfact
INNER JOIN Employeestatus on
Employeestatus.EmployeeID = workrecordfact.EmployeeID and
employeestatus.startdate <= workrecordfact.workdate and
employeestatus.enddate >= workrecordfact.workdate
INNER JOIN Positions on
employeestatus.PositionID = positions.PositionID
Where workrecordfact.workdate >= '20180601'
and workrecordfact.workdate <= '20180930'
and PositionCode = 'CSR'
Workrecordfact在Workdate上具有聚集索引
Employeestatus有4个索引
在查询Statistics中,我看到了很多500%的元素。从聚簇索引开始寻找WorkRecordFact索引。一些突出的数字
结果花费的时间太长,以致在某些情况下发送查询的.net应用接收超时。
我已经重建/重组了碎片索引,并刷新了统计信息,但这并不能解决问题。
有什么想法吗?
更新:似乎该查询在SMSS中运行得很好,并且仅在应用程序中超时。日期作为参数BTW传入,目前正在调查参数嗅探可能出现的问题:-/
答案 0 :(得分:0)
由于workrecordfact具有比EmployeeStatus多得多的记录,并且是日期范围查询。 首先索引它们总是很痛苦。
在我看来,第二次删除关于“员工身份”的索引对于此查询没有用。
EmployeeID
EmployeeID+ StartDate
EmployeeID+ EndDate
EmployeeID+ StartDate + EndDate
在事实表上为EmployeeID再创建一个。 我认为应该有帮助。
答案 1 :(得分:0)
游戏的名称是限制workrecordfact表上的IO。当前设置查询和索引的方式是,我们将在第三季度扫描100%的工作,然后将其过滤到仅属于CSR的工作。我想知道CSR标准是否可能更具选择性,并使我们读取的行数更少?
此查询非常简洁,对吧?
SELECT es.EmployeeID, es.StartDate, es.EndDate
FROM Positions p
JOIN Employeestatus es
ON p.PositionID = es.PositionID
WHERE PositionCode = 'CSR'
“ CSR”可能恰好与“排名”行匹配。假设职位的工作大致相等,我们可能只需要阅读工作表的Q3部分的10%。
这样考虑以后再介绍工作事实。
SELECT w.*
FROM
(
SELECT es.EmployeeID, es.StartDate, es.EndDate
FROM Positions p
JOIN Employeestatus es
ON p.PositionID = es.PositionID
WHERE PositionCode = 'CSR'
) es2
JOIN workrecordfact w
ON es2.EmployeeID = w.EmployeeID
AND es2.startdate <= w.workdate AND w.workdate <= es2.enddate
WHERE
'2018-06-01' <= w.workdate AND w.workdate <= '2018-09-30'
此索引将最好地支持此查询:
CREATE INDEX WorkRecordFact_EmployeeId_WorkDate ON WorkRecordFact(EmployeeId, WorkDate)
将工作日期的条件选择逻辑上更早地移入查询可能会有所帮助:
SELECT w.*
FROM
(
SELECT es.EmployeeID,
CASE WHEN es.StartDate <= '2018-06-01' THEN '2018-06-01' ELSE es.StartDate END as StartDate,
CASE WHEN '2018-09-30' <= es.EndDate THEN '2018-09-30' ELSE es.EndDate END as EndDate
FROM Positions p
JOIN Employeestatus es
ON p.PositionID = es.PositionID
WHERE PositionCode = 'CSR'
) es2
JOIN workrecordfact w
ON es2.EmployeeID = w.EmployeeID
AND es2.startdate <= w.workdate AND w.workdate <= es2.enddate