Почему sp_executesql работает медленнее, когда параметры передаются как аргументы

Запрос 1: (молниеносно)

sp_executesql "select * from tablesView where Id = 1"

против.

Запрос 2: (слишком медленно)

sp_executesql "select * from tablesView where Id = @Id", N"@Id int", @Id=1

tablesView - a view containing multiple joins

LINQ всегда преобразует запросы в форму Query2 и, следовательно, производительность очень плохая.

Вопросы: Мне нужна причина для медленности запроса2, и любое разрешение, если оно есть. И разрешение для LINQ.

---- Дополнительные комментарии:

Удар производительности определенно из-за двух столбцов, которые используют функции ранжирования (row_number), но я не могу избежать их, мне они нужны.

Ответ 1

Я собираюсь выйти на конечность и предположить, что у вас много строк, где ID = 1.

Если нет, пожалуйста, поправьте меня.

Одна из возможных причин, по которой SQL Server обрабатывает ваш запрос медленным, заключается в том, что он смотрит на запрос и идет:

Хмм, интересно, что он собирается передать для этого параметра.
это будет 1? где у меня около миллиона строк?
или, возможно, 1742, где у меня всего 3 человека Я просто не знаю, мне лучше выполнить сканирование таблицы, чтобы создать план выполнения, который будет охватывать все мои базы.

Если столбец или набор столбцов имеют низкую избирательность (то есть число уникальных значений намного меньше числа строк), SQL Server иногда возвращается к таблицам или аналогичным, просто чтобы получить все строки детерминированным образом.

По крайней мере, это был мой опыт. В частности, я видел такое же поведение при выборе диапазона дат в таблицах с привязанными по времени данными, делая WHERE dt <= @dt AND dt >= @dt для получения всех строк, где @dt находится внутри периода времени в этой строке, возвращается к сканированию таблицы, а затем, когда я помещаю фактическую дату в SQL как литерал, она выполняется намного быстрее.

Проблема здесь в селективности, SQL Server не знает, как наилучшим образом удовлетворить все сценарии при построении плана выполнения для вашего оператора, поэтому он попытается угадать.

Попробуйте добавить подсказку запроса, чтобы указать типичное значение для параметра, то есть.:

sp_executesql "select * from tablesView where Id = @Id option (optimize for (@id = 1742))", N"@Id int", @Id=1

Ответ 3

  • Избегайте использования SELECT *
  • ADO.NET 3.5 есть "параметр quessing" в Linq 1 = TINYINT 2345 = SMALLINT 76357242 = INT.. в ADO.NET 4.0 параметр quessing заменяется стандартным типом данных INT 1 = INT, 2335 = INT, 76357242 = INT)