TSQL - вернуть все идентификаторы записей и отсутствующие идентификаторы, которые нам нужно заполнить - PullRequest
2 голосов
/ 05 ноября 2019

У меня есть работа, которую нужно автоматизировать, чтобы убедиться, что кэш для некоторых объектов в моей базе данных заполнен. У меня есть запрос ниже, использующий CTE и CROSS JOIN, но он работает не очень быстро, поэтому я уверен, что его можно улучшить.

Проблема:

  • У меня есть база данных сотрудников
  • У каждого сотрудника есть отчет с данными, составляемыми каждый месяц.
  • Каждый отчет имеет набор «компонентов», и каждый из этих компонентов «данные» извлекается из внешнего источника и кэшируется в моей базе данных.

Цель:

Я хочу настроить задание на получение группы идентификаторов компонентов для «отчета за этот месяц» и предварительное кэширование данных, если их не существует.

Мне нужно получить список сотрудников и компонентов, которые отсутствуют в кэше, для отчета за эти месяцы. Затем я настрою задание CRON для обработки очереди.

Вопрос

Мой запрос ниже медленный - есть ли более эффективный способ вернуть списоксотрудники и идентификаторы компонентов, которые отсутствуют в кэше?

Текущий SQL:

declare @reportDate datetime2 = '2019-10-01'; //the report publish date
declare @componentIds table (id int);         // store the ids of each cachable component
insert @componentIds(id) values(1),(2),(3),(4),(5);   

;WITH cteCounts 
AS (SELECT r.Id as reportId, cs.componentId,
   COUNT(1) AS ComponentCount
   FROM EmployeeReports r
   LEFT OUTER JOIN CacheStore cs on r.Id = cs.reportId and cs.componentId in (SELECT id FROM @componentIds)
   GROUP BY r.Id, cs.componentId)

SELECT e.Id, e.name, _c.id as componentId, r.Id as reportId
FROM Employees e
INNER JOIN EmployeeReports r on e.Id = r.employeeId and r.reportDate = @reportDate 
CROSS JOIN @componentIds _c
LEFT OUTER JOIN cteCounts AS cn
    ON _c.Id = cn.componentId AND r.Id = cn.reportId
WHERE cn.ComponentCount is null

1 Ответ

2 голосов
/ 05 ноября 2019

2 вещи, которые я могу предложить:

  • Используйте NOT EXISTS вместо LEFT JOIN + IS NULL. План выполнения может отличаться, когда вы сообщаете движку, что вам нужны записи, которые не встречаются в определенном наборе Vs. объединение и проверка того, что объединенный столбец имеет нулевое значение.

    SELECT e.Id, e.name, _c.id as componentId, r.Id as reportId
    FROM Employees e
    INNER JOIN EmployeeReports r on e.Id = r.employeeId and r.reportDate = @reportDate 
    CROSS JOIN @componentIds _c
    WHERE
        NOT EXISTS (SELECT 'no record' FROM cteCounts AS cn
                    WHERE _c.Id = cn.componentId AND r.Id = cn.reportId)
    
  • Используйте временные таблицы вместо таблиц CTE и / или переменных. Если вам приходится обрабатывать много строк, таблицы переменных фактически не имеют статистики, а некоторые сложные CTE могут на самом деле составлять паршивые планы выполнения. Попробуйте использовать временные таблицы вместо этих 2 и посмотрите, не повышается ли производительность. Также попробуйте создать соответствующие индексы для них, если число строк велико.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...