SQL Server вычисляет результаты, которые позже отбрасываются? - PullRequest
0 голосов
/ 30 мая 2018

В настоящее время мы работаем с SQL Server 2016, и мы заметили кое-что, что заставило нас задуматься.

Мы выполняли запрос к таблице, которая иногда вызывала деление на ноль.

Настройка выглядит примерно так

SELECT 
    PT.ID, SUM(FT.Value1 / FT.Value2)
FROM 
    PrimaryTable PT
JOIN 
    ForeignTable FT ON PT.ID = FT.ForeignID
WHERE 
    PT.Date >= @DateStart
    AND PT.Date < @DateEnd

Теперь исправление довольно очевидно, если использовать NULLIF на FT.Value2, чтобы избежать деления на ноль.

Однако мы не смогли найти ни одной строки, которая фактически заставила бы сервер столкнуться с этой проблемой вообще, если бы она была ограничена отфильтрованными датами.Любопытно, что это также не произошло надежно.Мы могли бы отследить, что это зависит от того, сколько строк действительно существует в обеих таблицах.Если это произошло - это было воспроизводимо.Однако, если другие операции добавляются, удаляются или изменяются строки, это может быть причиной того, что деление на ноль не происходит.

Сервер работает как машина Hyper-V с 8 виртуальными ядрами и достаточным объемом ОЗУ для установкиобе таблицы более чем в 10 раз.Поэтому я подумал, что причиной проблемы могут быть параллельные вычисления.

Действительно ли SQL Server вычисляет результаты столбцов перед фильтрацией по оператору where?Или почему это может привести к делению на ноль, если ни одна из затронутых строк на самом деле не вызовет такое деление.

1 Ответ

0 голосов
/ 30 мая 2018

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

Если вам удалось получить 2 разных плана запросов для успешного выполнения и неудачного запуска, выдолжно быть в состоянии это увидеть.

Если возможно, можно использовать предложение optimize for unknown или optimize for (Values), чтобы предотвратить это изменение поведения.

Как отмечает Джероен, это не гарантировано, вы можете исправить план с подсказкой USE PLAN, но ни одна из этих вещей не так желательна, как исправление самого запроса для решения проблемы.

...