Оптимизировать объединение запросов между датами - PullRequest
0 голосов
/ 29 сентября 2018

3 таблицы

  • WorkRecordfact - имеет рабочую дату (дату) - ~ 300000 строк
  • EmployeeStatus - начальная дата (дата), конечная дата (дата), PositionID - 450 строк
  • Positions - PositionID, PositionCode - 10 строк

Запросы для поиска данных при фильтрации 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 индекса

  • EmployeeID
  • EmployeeID + StartDate
  • EmployeeID + EndDate
  • EmployeeID + StartDate + EndDate

В статистике запроса я вижу много 500% элементов.Начиная с кластерного индекса. Найдите индекс WorkRecordFact.Некоторые цифры, которые выделяются

  • Расчетное количество строк 250
  • Расчетное количество строк для чтения 667
  • Количество выполнений 381
  • Числопрочитанных строк 49525952 ??!?!?
  • Фактическое количество строк 112018

Результаты занимают достаточно много времени, и приложение .net, отправляющее запрос, в некоторых случаях получает тайм-аут.

Я перестроил / реорганизовал фрагментированные индексы и обновил статистику, но это не решило проблему.

Есть идеи?

ОБНОВЛЕНИЕ: Кажется, запрос выполняется довольнохорошо из SMSS и только тайм-аут из приложения.Даты передаются как параметры BTW, в настоящее время исследуются возможные проблемы с анализом параметров: - /

Ответы [ 2 ]

0 голосов
/ 29 сентября 2018

Название игры - ограничение ввода-вывода в таблице workrecordfact.То, как в настоящее время настроены запрос и индексация, мы сканируем 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 точно соответствуетодин ряд позиций.Предполагая, что должности выполняют примерно одинаковую работу, нам, вероятно, нужно только прочитать 10% части рабочего стола Q3.

Думая о том, чтобы потом ввести рабочие факты, как это.

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
0 голосов
/ 29 сентября 2018

Поскольку workrecordfact имеет намного больше записей, чем EmployeeStatus и является запросом диапазона дат.Во-первых, их индексация - это всегда боль.

Во-вторых, на мой взгляд, отбрасывать индексы статуса сотрудника, которые бесполезны для этого запроса.

EmployeeID
EmployeeID+ StartDate
EmployeeID+ EndDate
EmployeeID+ StartDate + EndDate

Создать еще один для EmployeeID натаблица фактов.Я думаю, что это должно помочь.

...