То, почему делает параметризированный запрос, производит значительно более медленный план запросов по сравнению с непараметризированным запросом

Для этого вам необходимо понять, как работает функция уменьшения. Он ожидает 2 параметра: функцию и начальное значение для вашего аккумулятора.

(x, y) => x.includes(y) ?  x : [...x, y]

это функция, которая вызывается внутри редукционного вызова. для x передается аккумулятор, для y - текущее значение массива. Таким образом, эта функция принимает значение аккумулятора и текущего значения, проверяет, находится ли значение в аккумуляторе (с помощью include). Если это функция возвращает x, аккумулятор, но если y не в x, функция возвращает новый массив для аккумулятора со всеми элементами старого аккумулятора и новым значением x.

Это далеко не лучший способ удаления дубликатов из массива, потому что каждый цикл вы просматриваете по всему массиву. Если вам нужен массив без дубликатов, рассмотрите возможность использования множеств .

22
задан Craig Quillen 4 February 2009 в 07:23
поделиться

3 ответа

Кажется, что планировщик запроса принял решение в литеральном запросе, который основан на информации, которую это уже имеет. Это имело бы статистику, которую это может запросить эффективно на основе распространения данных, данных в Вашем определенном литерале.

Параметризированный запрос выбрал запрос, которому он верит, является самым справедливым для всех данных в Вашей таблице, которую Вы заметите, много вложенных циклов (производительность = плохо).

Возможно, Вы могли бы попытаться выполнить инструменты оптимизации базы данных на своей базе данных, чтобы видеть, могли ли некоторые индексы помочь Вам здесь?

Конкретно в Вашем запросе, попробуйте это:

declare @p0 int
set @p0 = 1000
select *
from foo
join bar on bar.x = foo.x
join baz on baz.y = foo.y
where foo.x = @p0
OPTION ( OPTIMIZE FOR (@p0 = 1000))

Но я опасался бы делать это, не будучи уверенным, что данные, содержавшиеся в этом запросе, не изменятся и что Ваш запрос на этом плане ВСЕГДА будет более эффективным.

8
ответ дан 29 November 2019 в 05:45
поделиться

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

Во втором, то, что Вы используете переменные маски, которые оценивают от механизма во время компиляции (Вы думали бы, что он должен смочь понять это, но у меня на самом деле были подобные проблемы с простым константным выражением!), ведя к низкой производительности.

Одним путем можно попытаться двигаться, это должно было бы перенести запрос в хранимую процедуру, которая берет параметр непосредственно и затем применяет его к запросу - что-то вроде этого:

CREATE PROCEDURE test
  @p0 int
AS
BEGIN
  select *
  from foo
  join bar on bar.x = foo.x
  join baz on baz.y = foo.y
  where foo.x = @p0
END

Это должно позволить оптимизатору точно "осуществлять сниффинг" параметра, Вы используете и генерируете оптимальный план запросов для Вас.

6
ответ дан 29 November 2019 в 05:45
поделиться

Ваша начальная точка должна быть профилировщиком SQL. Выполненный и через профилировщика, и видят то, что план запросов находится в каждом случае..., затем обновляют вопрос описать два плана.

Одной вещью, которой я верю, может быть проблема, то, что, если у Вас есть параметризированный запрос с одним множеством значений, оптимизатор может посмотреть на часть статистики/индексов и выбрать один способ сделать его, затем повторное использование, которые планируют все запросы - несмотря на него не быть особенно подходящим для другого множества значений. Аналогично, если план определяется, когда существует один набор данных (например, когда одна таблица является крошечной, поощряя сканирование таблицы), и затем Вы добавляете загрузки блока данных, план не может быть соответствующим. Ни один из них не влиял бы на запрос, который был плох как самый первый запрос для подготовленного оператора все же.

2
ответ дан 29 November 2019 в 05:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: