2015-03-05 4 views
3

Дано:Разница в производительности, требующие sp_executesql с динамическим SQL против параметров

CREATE PROCEDURE [dbo].[my_storedproc] 
    @param1 int, @param2 varchar(100) 
AS 
<<whatever>> 
GO 

Существуют известные различия в производительности между этими различными методами выполнения ?:

-- Method #1: 
declare @param1 int = 1 
declare @param2 varchar(100) = 'hello' 
exec my_storedproc @param1, @param2 

-- Method #2: 
exec my_storedproc @param1=1, @param2='hello' 

-- Method #3: 
declare @param1 int = 1 
declare @param2 varchar(100) = 'hello' 
declare @procname nvarchar(100) = N'my_storedproc @param1, @param2' 
declare @params nvarchar(4000) = N'@param1 int, @param2 varchar(100)' 
exec sp_executesql @procname, @params, @param1, @param2 

-- Method #4: 
declare @procname nvarchar(4000) = N'my_storedproc @param1=1, @param2=''hello''' 
exec sp_executesql @procname 

-- Method #5: 
declare @procname nvarchar(4000) = N'my_storedproc 1, ''hello''' 
exec sp_executesql @procname 

-- Method #6: 
declare @procname nvarchar(4000) = N'my_storedproc 1, ''hello''' 
exec (@procname) 

«Почему ты спрашиваешь?» ты спрашиваешь? Я пытаюсь найти способ для общего выполнения хранимых процедур, полностью основанных на метаданных, управляющая хранимая процедура, которая будет физически выполнять все остальные настроенные (в метаданных) хранимые процедуры ничего не знает о них, кроме того, что определено в метаданных. Внутри этого контроллера SP я не могу (в каком-либо практическом смысле) знать и объявлять конкретные физические параметры (с их требуемыми типами данных), необходимые для всех возможных хранимых процедур, которые могут быть вызваны - я пытаюсь найти способ их выполнения в целом, но, надеюсь, поддерживать достойную производительность (повторное использование планов запросов и т. д.).

+0

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

+1

Интересно, как люди SQL буквально не могут понять основополагающий принцип здесь - не только это не сумасшествие, это тот самый принцип, на котором основаны инструменты ORM. «Это похоже на создание единого метода в .NET, который может делать что угодно» Нет, это не так, у вас все еще есть отдельные хранимые процедуры. «стоимость будет производительностью». Это? Вот в чем вопрос. Это то, что хулители говорили о динамическом SQL с ORM, и они оказались неверными. – tbone

+3

Правильно, но ORM генерирует sql динамически. И я еще не видел ORM, который производит отличный sql. Это невероятно сложно, поэтому sql всегда настолько неуправляем. Я думаю, что sql, выходящий из чего-то с этим дополнительным слоем абстракции, будет еще более сумасшедшим. Я был бы очень осторожен в использовании методов 3 или 4, которые вы описали, потому что было бы трудно предотвратить внедрение sql без использования параметров. И метод 1 не будет достаточно общим для того, что вы пытаетесь сделать. –

ответ

1

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

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

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

Почему бы и нет? Я не понимаю, почему вы не можете динамически генерировать SQL для методов 2 и 3 основаны на выходе любого из следующих запросов:

SELECT OBJECT_NAME(sp.[object_id]), * 
FROM sys.parameters sp 
WHERE sp.[object_id] = OBJECT_ID(N'dbo.my_storedproc'); 

SELECT isp.* 
FROM INFORMATION_SCHEMA.PARAMETERS isp 
WHERE isp.[SPECIFIC_NAME] = N'my_storedproc' 
AND isp.[SPECIFIC_SCHEMA] = N'dbo'; 

И с этой информацией, вы можете создать таблицу, чтобы содержать различные значения параметров для каждого параметра для каждого proc. Фактически, вы даже можете настроить его, чтобы иметь некоторые параметры с «глобальными» значениями для всех вариантов, а затем некоторые значения параметров являются вариациями для конкретной процедуры.

+0

Все SQL хранится как метаданные, это смесь простых вызовов SQL и хранимых процедур, а некоторые из них ссылаются на удаленные SQL-серверы. – tbone

+0

@tbone Текст вопроса и примеры относятся только к сохраненным процессам, вызываемым этой установкой. Если установка также будет вызывать динамический SQL, тогда могут быть различия в производительности между некоторыми из этих 6 вариантов. И тогда, конечно, даже если есть параметры, они не будут доступны для поиска по двум запрошенным мной запросам. –

+0

Я думаю, что мои проблемы, связанные с этой проблемой (производительность динамического sql, включая параметры через sp_executesql), могут быть устранены, переместив это в SQLCLR. Вы хорошо разбираетесь в двух ваших примерах запросов, но мне также нужно учитывать текст запроса, не основанный на SP. С правильно сформированными запросами через SQLCLR, однако, я ожидал бы, что характеристики производительности того, что я делаю, будут по существу такими же, как и любая стандартная ORM (что, по-видимому, большинство администраторов DBA ненавидят, но я не думаю, что есть много оправданий для этого если они используются правильно.) – tbone