Параметрированный SQL-in/not in с фиксированным количеством параметров для оптимизации кеша плана запроса?

Если SQL используется напрямую или создается NHibernate, возможно, с большим значением "где in/not in ([от 1 до 100 параметров])", имеет ли смысл заполнять параметры до определенных пределов, иметь ограниченное число планов запросов?

Параметры - int/number, СУБД - MSSQL или Oracle. Запросы вызываются через sp_executesql/executeimmediate, чтобы обеспечить кэширование плана запроса.

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

Пользователь может заполнить список параметров, повторив последнее значение, пока не будет достигнуто определенное количество параметров?

Насколько я знаю, MSSQL и Oracle идентифицируют известные запросы посредством равенства строк, что приводит к другому тарифному плану для каждого разного количества параметров.

(значения, конечно, будут параметрами, а не конкатенированными числами).

SELECT * FROM MyTable WHERE Id in (4001, 4002, 4003, ... , 4055, 4056)

с 56 параметрами, измените на:

SELECT * FROM MyTable WHERE Id in (4001, 4002, 4003, ... , 4055, 4056, 4056, 4056, 4056, 4056)

имеет 60 параметров, повторяя значение 4056, причем все длинные "в" списки имеют длины 50, 60, 70, 80, 90, 100. Осталось меньше 10 параметров.

Для такого запроса с до 100 параметрами будет 10 планов запросов для 10 - 100 параметров, а также 9 планов запросов для 1-9 параметров (без заполнения).

РЕДАКТИРОВАТЬ: Я обнаружил, что NHibernate (3.1.0.4 или новее) и SQL Server с пакетным размером = "200" фактически разбивают списки параметров на несколько операторов с фиксированными параметрами длины. Например, выберите с 118 идентификационными параметрами, а пакетный размер = "200" может быть отправлен как три выбора с 100, 12 и 6 идентификаторами вместо одного с 118 идентификаторами. Это похоже на то, что я хотел, batch-size = "200" , а не с 200 различными строками SQL и, таким образом, планы запросов, накапливающиеся с течением времени, но только меньшее число, возможно, 16. Кажется, что один SQL для каждого значения параметра между 1 и 12, затем заявления с параметрами 25, 50 и 100. Возможно, заполнение с повторным значением - может быть более эффективным, но это хороший способ повторного использования плана запроса.

Ответ 1

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

Если они достаточно статичны, поместите их в таблицу фильтров и выполните:

SELECT t.*
FROM MyTable t
INNER JOIN FilterTable f ON t.Id = f.Id

Если они полностью динамичны, используйте параметр Table Valued Parameter. В SQL Server 2008 я могу передать табличный параметр в мою хранимую процедуру из NHibernate. Как добиться того же в Oracle