Можно ли по умолчанию настроить / использовать sp_executesql?

10

Я смотрю на приложение, которое использует высокодинамичные запросы SQL против SQL Server. Глядя на запросы, которые составлены очень странными и сложными способами, но это уже другая история, я расскажу это, чтобы дать вескую причину того, что я не в состоянии (слишком глупо) самому что-то выяснить ... Я не вижу любой код, к которому относятся запросы sp_executesql.

Но когда я прослеживаю, я вижу много запросов, приходящих в завершение sp_executesql. Целое прикладное решение даже не содержит команды sp_executesqlвообще.

Поэтому мне стало интересно, есть ли какая-то конфигурация, которую я еще не знаю, которая заставляет программное обеспечение по умолчанию оборачивать запросы sp_executesql?

Что может вызвать такое поведение?

Magier
источник

Ответы:

11

Причиной переноса операторов SQL sp_executesqlявляется установка SqlCommand.Commandtypeсвойства и передача в команду любых параметров.

SqlCommand cmd = new SqlCommand("proc1", con);
cmd.CommandType = CommandType.StoredProcedure;                
cmd.Parameters.AddWithValue("@param1", 1);
con.Open();
cmd.ExecuteNonQuery();
con.Close();

Код выше заканчивается этим T-SQL:

exec proc1 @param1=1
SqlCommand cmd = new SqlCommand("proc1", con);
cmd.CommandType = CommandType.Text;                
cmd.Parameters.AddWithValue("@param1", 1);
con.Open();
cmd.ExecuteNonQuery();
con.Close();

Этот код заканчивается выполнением следующего T-SQL:

exec sp_executesql N'proc1',N'@param1 int',@param1=1

Дополнение 23.12.15: Использование CommandType.Textкоманды приводит к аналогичным результатам: как только параметр добавляется в объект команды, .NET обернет весь запрос sp_executesqlи передаст ему параметры.

Дополнение. После более глубокого погружения в sp_executesqlанализ параметров и кэширования планов такое поведение классов .NET полностью приобретает смысл во избежание частой компиляции запросов и количества планов. Таким образом, он в основном предназначен для обеспечения большей производительности SQL Server в целом, в то же время он может привести к низкой производительности некоторых запросов (проблема с анализом параметров), которые используются с значениями параметров, отличными от первоначально созданного плана запроса.

Увидеть:

Приведенный выше пример был создан с использованием .NET Framework 4.5 и SQL Server 2008 Developer Edition.

Magier
источник
5

Если это приложение .NET, то, скорее всего, это результат вызова SqlCommand.ExecuteReader () . Согласно главной странице класса SqlCommand , в таблице описаний методов в разделе «Замечания» в ExecuteReader говорится:

Выполняет команды, которые возвращают строки. Для повышения производительности ExecuteReader вызывает команды, используя системную хранимую процедуру Transact-SQL sp_executesql . Следовательно, ExecuteReader может не дать желаемого эффекта, если он используется для выполнения команд, таких как инструкции Transact-SQL SET.

Сейчас у меня нет времени, чтобы проверить это, чтобы подтвердить их описание, но должно быть достаточно просто создать простое консольное приложение, которое выполняет очень простой вызов, передает некоторый текст запроса и включает параметр, который поставляется вместе с SqlParameter. Я думаю, что ExecuteNonQueryи ExecuteScalarиспользовать , sp_executesqlтак как они позволяют также для передачи в параметрах, так почему бы там быть другой путь для того, как те , которые выполняются?

Соломон Руцкий
источник