Параметры, вызывающие замедление запроса - PullRequest
0 голосов
/ 19 сентября 2019

У меня есть этот запрос

DECLARE @Company VARCHAR(20) = 'ABC'
DECLARE @Train INT = 1

SELECT L.*
FROM vemd_episodes_firstnet_currentPatients L 
INNER JOIN vemd_episodes E ON E.Company = L.Company 
                           AND E.cpid = L.cpid  
                           AND E.dDate = L.dDate
WHERE L.Company = @Company
  AND ((census_datetime NOT IN (SELECT MAX(census_datetime) FROM vemd_episodes_firstnet_currentPatients ) AND @Train = 1)
       OR (census_datetime IN (SELECT MAX(census_datetime) FROM vemd_episodes_firstnet_currentPatients ) AND @Train = 0))

Для завершения требуется вечность.

Через 1 минуту он извлекает только 400 записей и все еще работает.

Общее количествозаписей для этого запроса должно быть около 500 000 записей.

enter image description here

Но когда я жестко закодирую параметры в запросе

SELECT L.*
FROM vemd_episodes_firstnet_currentPatients L 
INNER JOIN vemd_episodes E ON E.Company = L.Company 
                           AND E.cpid = L.cpid  
                           AND E.dDate = L.dDate
WHERE L.Company = 'ABC'
  AND ((census_datetime NOT IN (SELECT MAX(census_datetime) FROM vemd_episodes_firstnet_currentPatients ) AND 1 = 1)
       OR (census_datetime IN (SELECT MAX(census_datetime) FROM vemd_episodes_firstnet_currentPatients ) AND 1 = 0))

он очень быстрый и извлекает 500 тыс. записей за 16 секунд.

Почему использование параметров в предложении where вызывает эту проблему?И как это исправить?

Редактировать:

Я не мог продолжать работать до конца

, поэтому я выбираютоп 1000 и получил план выполнения

enter image description here

Ответы [ 2 ]

2 голосов
/ 19 сентября 2019

Вы можете попробовать запрос с параметром перекомпиляции OPTION (RECOMPILE) При параметризованных запросах SQL иногда выбирает неправильный план выполнения и настаивает на его использовании.

DECLARE @Company VARCHAR(20) = 'ABC'
DECLARE @Train INT = 1

SELECT L.*
FROM vemd_episodes_firstnet_currentPatients L 
INNER JOIN vemd_episodes E ON E.Company = L.Company 
                           AND E.cpid = L.cpid  
                           AND E.dDate = L.dDate
WHERE L.Company = @Company
  AND ((census_datetime NOT IN (SELECT MAX(census_datetime) FROM vemd_episodes_firstnet_currentPatients ) AND @Train = 1)
       OR (census_datetime IN (SELECT MAX(census_datetime) FROM vemd_episodes_firstnet_currentPatients ) AND @Train = 0))
OPTION  (RECOMPILE)
0 голосов
/ 19 сентября 2019

Попробуйте использовать оконные функции:

SELECT L.*
FROM (SELECT L.*,
             MAX(census_datetime) OVER () as max_census_datetime
      FROM vemd_episodes_firstnet_currentPatients L 
     ) L JOIN
     vemd_episodes E
     ON E.Company = L.Company AND
        E.cpid = L.cpid AND
        E.dDate = L.dDate
WHERE L.Company = @Company AND
      ((census_datetime <> max_census_datetime AND @Train = 1) OR
       (census_datetime = max_census_datetime AND @Train = 0)
      );

Оптимизатору должно быть проще сгенерировать соответствующий план выполнения с более простым предложением where.

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