Любая идея, почему IF EXISTS
заставило бы это бежать намного дольше и делать так много чтений? Я также изменил оператор выбора, чтобы сделать, SELECT TOP 1 [dlc].[id]
и я убил его через 2 минуты.
Как я объяснил в своем ответе на этот связанный вопрос:
Как (и почему) TOP влияет на план выполнения?
С помощью EXISTS
вводит цель строки, где оптимизатор создает план выполнения, нацеленный на быстрое нахождение первой строки. При этом предполагается, что данные распределены равномерно. Например, если статистика показывает, что в 100 000 строк есть 100 ожидаемых совпадений, она будет предполагать, что для поиска первого совпадения потребуется прочитать только 1000 строк.
Это приведет к увеличению времени выполнения, если это предположение окажется ошибочным. Например, если SQL Server выбирает метод доступа (например, неупорядоченное сканирование), который обнаруживает первое совпадающее значение очень поздно при поиске, это может привести к почти полному сканированию. С другой стороны, если в первых нескольких строках будет найдена совпадающая строка, производительность будет очень хорошей. Это фундаментальный риск для ряда целей - непоследовательная производительность.
В качестве временного исправления я изменил его на счетчик (*) и присвоил это значение переменной
Обычно можно переформулировать запрос так, чтобы цель строки не была назначена. Без цели строки запрос все еще может быть завершен при обнаружении первой подходящей строки (если она написана правильно), но стратегия плана выполнения, вероятно, будет другой (и, надеюсь, более эффективной). Очевидно, что count (*) потребует чтения всех строк, поэтому это не идеальная альтернатива.
Если вы работаете с SQL Server 2008 R2 или более поздней версии , вы также можете использовать документированный и поддерживаемый флаг трассировки 4138, чтобы получить план выполнения без цели строки. Этот флаг также может быть указан с помощью поддерживаемой подсказки OPTION (QUERYTRACEON 4138)
, хотя имейте в виду , что для этого требуется разрешение системного администратора во время выполнения , если только оно не используется с руководством по планированию.
к несчастью
Ничто из вышеперечисленного не является функциональным с IF EXISTS
условным утверждением. Это относится только к обычному DML. Это будет работать с альтернативной SELECT TOP (1)
формулировкой, которую вы пробовали. Это может быть лучше, чем использоватьCOUNT(*)
, которое должно подсчитывать все подходящие строки, как упоминалось ранее.
Тем не менее, существует множество способов выразить это требование, которое позволит вам избежать или контролировать цель строки, в то же время досрочно завершив поиск. Последний пример:
DECLARE @Exists bit;
SELECT @Exists =
CASE
WHEN EXISTS
(
SELECT [dlc].[ID]
FROM TableDLC [dlc]
JOIN TableD [d]
ON [d].[ID] = [dlc].[ID]
JOIN TableC [c]
ON [c].[ID] = [d].[ID2]
WHERE [c].[Name] <> [dlc].[Name]
)
THEN CONVERT(bit, 1)
ELSE CONVERT(bit, 0)
END
OPTION (QUERYTRACEON 4138);
IF @Exists = 1
BEGIN
...
END;
IF NOT EXISTS (...) BEGIN END ELSE BEGIN <do something> END
.