SQL Server: быстрый запрос, но медленный от процедуры

Запрос выполняется быстро:

DECLARE @SessionGUID uniqueidentifier
SET @SessionGUID = 'BCBA333C-B6A1-4155-9833-C495F22EA908'

SELECT *
FROM Report_Opener
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank

стоимость поддерева: 0,502

Но размещение одного и того же SQL в хранимой процедуре выполняется медленно и с совершенно другим планом выполнения

CREATE PROCEDURE dbo.ViewOpener @SessionGUID uniqueidentifier AS
SELECT *
FROM Report_Opener
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank

EXECUTE ViewOpener @SessionGUID

Стоимость субтитров: 19.2

Я запустил

sp_recompile ViewOpener

И он по-прежнему работает одинаково (плохо), и я также изменил сохраненный процедуры для

CREATE PROCEDURE dbo.ViewOpener @SessionGUID uniqueidentifier AS
SELECT *, 'recompile please'
FROM Report_Opener
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank

И снова, пытаясь по-настоящему обмануть его в перекомпиляцию.

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

Я попытался принудительно перекомпилировать и предотвратить параметр sniffing, используя переменную decoy:

CREATE PROCEDURE dbo.ViewOpener @SessionGUID uniqueidentifier AS

DECLARE @SessionGUIDbitch uniqueidentifier
SET @SessionGUIDbitch = @SessionGUID

SELECT *
FROM Report_Opener
WHERE SessionGUID = @SessionGUIDbitch
ORDER BY CurrencyTypeOrder, Rank

Я также попытался определить хранимую процедуру WITH RECOMPILE:

CREATE PROCEDURE dbo.ViewOpener @SessionGUID uniqueidentifier 
WITH RECOMPILE
AS
SELECT *
FROM Report_Opener
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank

Так, чтобы он планировался, он никогда не кэшируется, и я пытался заставить перекомпилировать при выполнении:

EXECUTE ViewOpener @SessionGUID WITH RECOMPILE

Что не помогло.

Я попытался преобразовать процедуру в динамический SQL:

CREATE PROCEDURE dbo.ViewOpener @SessionGUID uniqueidentifier 
WITH RECOMPILE AS
DECLARE @SQLString NVARCHAR(500)

SET @SQLString = N'SELECT *
   FROM Report_OpenerTest
   WHERE SessionGUID = @SessionGUID
   ORDER BY CurrencyTypeOrder, Rank'

EXECUTE sp_executesql @SQLString,
N'@SessionGUID uniqueidentifier',
@SessionGUID

Что не помогло.

Объект "Report_Opener" - это представление, которое не индексируется. Вид ссылается только на базовые таблицы. В таблице нет вычисленных столбцов, индексированных или других.

В сущности, я попытался создать представление с помощью

SET ANSI_NULLS ON
SET QUOTED_IDENTIFER ON

Это не исправить.

Как это, что

  • запрос выполняется быстро
  • перемещение запроса в представление, а выбор из представления выполняется быстро
  • выбор из представления из хранимой процедуры в 40 раз медленнее?

Я попытался переместить определение представления непосредственно в хранимую процедуру (нарушив 3 бизнес-правила и сломав важную инкапсуляцию), и это делает ее примерно на 6x медленнее.

Почему версия хранимой процедуры настолько медленная? Что может объяснить SQL Server, работающий с ad-hoc SQL быстрее, чем другой тип SQL?

Я бы предпочел не

  • встроить SQL в код
  • изменить код вообще

    Microsoft SQL Server  2000 - 8.00.2050 (Intel X86)
    Mar  7 2008 21:29:56
    Copyright (c) 1988-2003 Microsoft Corporation
    Standard Edition on Windows NT 5.2 (Build 3790: Service Pack 2)
    

Но что может означать, что SQL Server не может работать так же быстро, как SQL Sever, выполняющий запрос, если не параметр sniffing.


Моя следующая попытка будет заключаться в вызове StoredProcedureA call StoredProcedureB call StoredProcedureC call StoredProcedureD, чтобы запросить представление.

И если это не так, попросите хранимую процедуру вызвать хранимую процедуру, вызовите UDF, вызовите UDF, вызовите хранимую процедуру, вызовите UDF, чтобы запросить представление.


Подводя итог, следуйте быстрому выполнению QA, но медленно, когда помещается в хранимую процедуру:

Оригинал:

--Runs fine outside of a stored procedure
SELECT *
FROM Report_OpenerTest
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank

sp_executesql:

--Runs fine outside of a stored procedure
DECLARE @SQLString NVARCHAR(500)
SET @SQLString = N'SELECT *
FROM Report_OpenerTest
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank'

EXECUTE sp_executesql @SQLString,
        N'@SessionGUID uniqueidentifier',
        @SessionGUID

EXEC(@sql):

--Runs fine outside of a stored procedure
DECLARE @sql NVARCHAR(500)
SET @sql = N'SELECT *
FROM Report_OpenerTest
WHERE SessionGUID = '''+CAST(@SessionGUID AS varchar(50))+'''
ORDER BY CurrencyTypeOrder, Rank'

EXEC(@sql)

Планы выполнения

План хороший:

      |--Sort(ORDER BY:([Expr1020] ASC, [Currencies].[Rank] ASC))
           |--Compute Scalar(DEFINE:([Expr1020]=If ([Currencies].[CurrencyType]='ctCanadianCash') then 1 else If ([Currencies].[CurrencyType]='ctMiscellaneous') then 2 else If ([Currencies].[CurrencyType]='ctTokens') then 3 else If ([Currencies].[CurrencyType]
                |--Nested Loops(Left Outer Join, OUTER REFERENCES:([Openers].[OpenerGUID]))
                     |--Filter(WHERE:((([Currencies].[IsActive]<>0 AND [Currencies].[OnOpener]<>0) AND ((((((([Currencies].[CurrencyType]='ctUSCoin' OR [Currencies].[CurrencyType]='ctMiscellaneousUS') OR [Currencies].[CurrencyType]='ctUSCash') OR [Currencies].
                     |    |--Nested Loops(Left Outer Join, OUTER REFERENCES:([Currencies].[CurrencyGUID], [Openers].[OpenerGUID]) WITH PREFETCH)
                     |         |--Nested Loops(Left Outer Join)
                     |         |    |--Bookmark Lookup(BOOKMARK:([Bmk1016]), OBJECT:([GrobManagementSystemLive].[dbo].[Windows]))
                     |         |    |    |--Nested Loops(Inner Join, OUTER REFERENCES:([Openers].[WindowGUID]))
                     |         |    |         |--Bookmark Lookup(BOOKMARK:([Bmk1014]), OBJECT:([GrobManagementSystemLive].[dbo].[Openers]))
                     |         |    |         |    |--Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[Openers].[IX_Openers_SessionGUID]), SEEK:([Openers].[SessionGUID]=[@SessionGUID]) ORDERED FORWARD)
                     |         |    |         |--Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[Windows].[IX_Windows]), SEEK:([Windows].[WindowGUID]=[Openers].[WindowGUID]) ORDERED FORWARD)
                     |         |    |--Clustered Index Scan(OBJECT:([GrobManagementSystemLive].[dbo].[Currencies].[IX_Currencies_CurrencyType]))
                     |         |--Clustered Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[OpenerDetails].[IX_OpenerDetails_OpenerGUIDCurrencyGUID]), SEEK:([OpenerDetails].[OpenerGUID]=[Openers].[OpenerGUID] AND [OpenerDetails].[CurrencyGUID]=[Currenc
                     |--Hash Match(Cache, HASH:([Openers].[OpenerGUID]), RESIDUAL:([Openers].[OpenerGUID]=[Openers].[OpenerGUID]))
                          |--Stream Aggregate(DEFINE:([Expr1006]=SUM(If (((([Currencies].[CurrencyType]='ctMiscellaneous' OR [Currencies].[CurrencyType]='ctTokens') OR [Currencies].[CurrencyType]='ctChips') OR [Currencies].[CurrencyType]='ctCanadianCoin') OR [
                               |--Nested Loops(Inner Join, OUTER REFERENCES:([OpenerDetails].[CurrencyGUID]) WITH PREFETCH)
                                    |--Nested Loops(Inner Join)
                                    |    |--Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[Openers].[IX_Openers_OneOpenerPerSession]), SEEK:([Openers].[OpenerGUID]=[Openers].[OpenerGUID]) ORDERED FORWARD)
                                    |    |--Clustered Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[OpenerDetails].[IX_OpenerDetails_OpenerGUIDCurrencyGUID]), SEEK:([OpenerDetails].[OpenerGUID]=[Openers].[OpenerGUID]) ORDERED FORWARD)
                                    |--Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[Currencies].[PK_Currencies_CurrencyGUID]), SEEK:([Currencies].[CurrencyGUID]=[OpenerDetails].[CurrencyGUID]) ORDERED FORWARD)

План плохой

       |--Sort(ORDER BY:([Expr1020] ASC, [Currencies].[Rank] ASC))
            |--Compute Scalar(DEFINE:([Expr1020]=If ([Currencies].[CurrencyType]='ctCanadianCash') then 1 else If ([Currencies].[CurrencyType]='ctMiscellaneous') then 2 else If ([Currencies].[CurrencyType]='ctTokens') then 3 else If ([Currencies].[Currency
                 |--Nested Loops(Left Outer Join, OUTER REFERENCES:([Openers].[OpenerGUID]))
                      |--Filter(WHERE:((([Currencies].[IsActive]<>0 AND [Currencies].[OnOpener]<>0) AND ((((((([Currencies].[CurrencyType]='ctUSCoin' OR [Currencies].[CurrencyType]='ctMiscellaneousUS') OR [Currencies].[CurrencyType]='ctUSCash') OR [Currenc
                      |    |--Nested Loops(Left Outer Join, OUTER REFERENCES:([Currencies].[CurrencyGUID], [Openers].[OpenerGUID]) WITH PREFETCH)
                      |         |--Filter(WHERE:([Openers].[SessionGUID]=[@SessionGUID]))
                      |         |    |--Concatenation
                      |         |         |--Nested Loops(Left Outer Join)
                      |         |         |    |--Table Spool
                      |         |         |    |    |--Hash Match(Inner Join, HASH:([Windows].[WindowGUID])=([Openers].[WindowGUID]), RESIDUAL:([Windows].[WindowGUID]=[Openers].[WindowGUID]))
                      |         |         |    |         |--Clustered Index Scan(OBJECT:([GrobManagementSystemLive].[dbo].[Windows].[IX_Windows_CageGUID]))
                      |         |         |    |         |--Table Scan(OBJECT:([GrobManagementSystemLive].[dbo].[Openers]))
                      |         |         |    |--Table Spool
                      |         |         |         |--Clustered Index Scan(OBJECT:([GrobManagementSystemLive].[dbo].[Currencies].[IX_Currencies_CurrencyType]))
                      |         |         |--Compute Scalar(DEFINE:([Openers].[OpenerGUID]=NULL, [Openers].[SessionGUID]=NULL, [Windows].[UseChipDenominations]=NULL))
                      |         |              |--Nested Loops(Left Anti Semi Join)
                      |         |                   |--Clustered Index Scan(OBJECT:([GrobManagementSystemLive].[dbo].[Currencies].[IX_Currencies_CurrencyType]))
                      |         |                   |--Row Count Spool
                      |         |                        |--Table Spool
                      |         |--Clustered Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[OpenerDetails].[IX_OpenerDetails_OpenerGUIDCurrencyGUID]), SEEK:([OpenerDetails].[OpenerGUID]=[Openers].[OpenerGUID] AND [OpenerDetails].[CurrencyGUID]=[Cu
                      |--Hash Match(Cache, HASH:([Openers].[OpenerGUID]), RESIDUAL:([Openers].[OpenerGUID]=[Openers].[OpenerGUID]))
                           |--Stream Aggregate(DEFINE:([Expr1006]=SUM([partialagg1034]), [Expr1007]=SUM([partialagg1035]), [Expr1008]=SUM([partialagg1036]), [Expr1009]=SUM([partialagg1037]), [Expr1010]=SUM([partialagg1038]), [Expr1011]=SUM([partialagg1039]
                                |--Nested Loops(Inner Join)
                                     |--Stream Aggregate(DEFINE:([partialagg1034]=SUM(If (((([Currencies].[CurrencyType]='ctMiscellaneous' OR [Currencies].[CurrencyType]='ctTokens') OR [Currencies].[CurrencyType]='ctChips') OR [Currencies].[CurrencyType]='
                                     |    |--Nested Loops(Inner Join, OUTER REFERENCES:([OpenerDetails].[CurrencyGUID]) WITH PREFETCH)
                                     |         |--Clustered Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[OpenerDetails].[IX_OpenerDetails_OpenerGUIDCurrencyGUID]), SEEK:([OpenerDetails].[OpenerGUID]=[Openers].[OpenerGUID]) ORDERED FORWARD)
                                     |         |--Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[Currencies].[PK_Currencies_CurrencyGUID]), SEEK:([Currencies].[CurrencyGUID]=[OpenerDetails].[CurrencyGUID]) ORDERED FORWARD)
                                     |--Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[Openers].[IX_Openers_OneOpenerPerSession]), SEEK:([Openers].[OpenerGUID]=[Openers].[OpenerGUID]) ORDERED FORWARD)

Плохое одно нетерпеливо буферизует 6 миллионов строк; другой - нет.

Примечание.. Это не вопрос настройки запроса. У меня есть запрос, который работает молниеносно. Я просто хочу, чтобы SQL Server быстро запускался из хранимой процедуры.

Ответ 1

Я нашел проблему, здесь script медленных и быстрых версий хранимой процедуры:

dbo.ViewOpener__RenamedForCruachan__Slow.PRC

SET QUOTED_IDENTIFIER OFF 
GO
SET ANSI_NULLS OFF 
GO

CREATE PROCEDURE dbo.ViewOpener_RenamedForCruachan_Slow
    @SessionGUID uniqueidentifier
AS

SELECT *
FROM Report_Opener_RenamedForCruachan
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank
GO

SET QUOTED_IDENTIFIER OFF 
GO
SET ANSI_NULLS ON 
GO

dbo.ViewOpener__RenamedForCruachan__Fast.PRC

SET QUOTED_IDENTIFIER OFF 
GO
SET ANSI_NULLS ON 
GO

CREATE PROCEDURE dbo.ViewOpener_RenamedForCruachan_Fast
    @SessionGUID uniqueidentifier 
AS

SELECT *
FROM Report_Opener_RenamedForCruachan
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank
GO

SET QUOTED_IDENTIFIER OFF 
GO
SET ANSI_NULLS ON 
GO

Если вы не заметили разницу, я не обвиняю вас. Разница не во всей хранимой процедуре. Разница, которая превращает быстрый 0,5-разрядный запрос в тот, который выполняет энергичную катушку в 6 миллионов строк:

Медленное: SET ANSI_NULLS OFF

Быстрый: SET ANSI_NULLS ON


Этот ответ также может иметь смысл, поскольку в представлении есть предложение соединения, в котором говорится:

(table.column IS NOT NULL)

Таким образом, существует несколько NULL.


Объяснение дополнительно подтверждается возвратом в Query Analizer и запуском

SET ANSI_NULLS OFF

.

DECLARE @SessionGUID uniqueidentifier
SET @SessionGUID = 'BCBA333C-B6A1-4155-9833-C495F22EA908'

.

SELECT *
FROM Report_Opener_RenamedForCruachan
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank

И запрос выполняется медленно.


Таким образом, проблема не, потому что запрос выполняется из хранимой процедуры. Проблема заключается в том, что параметр подключения по умолчанию для Enterprise Manager - ANSI_NULLS off, а не ANSI_NULLS on, который по умолчанию является QA.

Microsoft подтверждает этот факт в KB296769 (BUG: не удается использовать SQL Enterprise Manager для создания хранимых процедур, содержащих связанные объекты сервера). Обходной путь включает параметр ANSI_NULLS в диалоговом окне хранимой процедуры:

Set ANSI_NULLS ON
Go
Create Proc spXXXX as
....

Ответ 2

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

Я нашел еще один ответ здесь "Параметр Sniffing" , спасибо Omnibuzz. Срабатывает до использования "локальных переменных" в ваших запросах хранимой процедуры, но читайте оригинал для большего понимания, это отличная запись. например.

Медленный путь:

CREATE PROCEDURE GetOrderForCustomers(@CustID varchar(20))
AS
BEGIN
    SELECT * 
    FROM orders
    WHERE customerid = @CustID
END

Быстрый способ:

CREATE PROCEDURE GetOrderForCustomersWithoutPS(@CustID varchar(20))
AS
BEGIN
    DECLARE @LocCustID varchar(20)
    SET @LocCustID = @CustID

    SELECT * 
    FROM orders
    WHERE customerid = @LocCustID
END

Надеюсь, это поможет кому-то другому, это сократит время выполнения от 5 до 6-7 секунд.

Ответ 3

Сделайте это для своей базы данных. У меня та же проблема - она отлично работает в одной базе данных, но когда я копирую эту базу данных в другую, используя импорт служб SSIS (не обычное восстановление), эта проблема возникает с большинством моих хранимых процедур. Поэтому, погуглив еще немного, я нашел блог Пинала Дейва (между прочим, я столкнулся с большинством его постов и очень мне помог, так что спасибо Пиналу Дейву).

Я выполняю следующий запрос к моей базе данных, и это исправило мою проблему:

EXEC sp_MSforeachtable @command1="print '?' DBCC DBREINDEX ('?', ' ', 80)"
GO
EXEC sp_updatestats
GO 

Надеюсь это поможет. Просто передавая помощь от других, которые помогли мне.

Ответ 4

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

fooobar.com/questions/33172/...

В конце вашего запроса добавьте OPTION (OPTIMIZE FOR (@now UNKNOWN))

Ответ 5

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

Ответ 6

Я столкнулся с этой проблемой. Мой запрос выглядел примерно так:

select a, b, c from sometable where date > '20140101'

Моя хранимая процедура была определена следующим образом:

create procedure my_procedure (@dtFrom date)
as
select a, b, c from sometable where date > @dtFrom

Я изменил тип данных на datetime и voila! Пошел от 30 минут до 1 минуты!

create procedure my_procedure (@dtFrom datetime)
as
select a, b, c from sometable where date > @dtFrom

Ответ 7

Хотя я обычно против этого (хотя в этом случае кажется, что у вас есть настоящая причина), попробовали ли вы дать какие-либо подсказки по запросу версии SP запроса? Если SQL Server готовит другой план выполнения в этих двух экземплярах, можете ли вы использовать подсказку, чтобы сообщить, какой индекс использовать, чтобы план соответствовал первому?

Для некоторых примеров вы можете перейти сюда.

EDIT: если вы можете опубликовать свой план запроса здесь, возможно, мы сможем определить некоторую разницу между планами, которые говорят.

SECOND: Обновлена ​​ссылка для SQL-2000. Вам придется прокручивать путь, но там есть второй под названием "Настольные подсказки", который вы ищете.

THIRD: "Плохой" запрос, кажется, игнорирует [IX_Openers_SessionGUID] в таблице "Openers" - любой шанс добавить подсказку INDEX, чтобы заставить ее использовать этот индекс, изменит ситуацию?

Ответ 8

Вы пытались перестроить статистику и/или индексы в таблице Report_Opener. Все рекомплексы SP не будут стоить ничего, если статистика по-прежнему будет отображать данные, когда база данных была впервые введена.

Исходный запрос сам по себе работает быстро, потому что оптимизатор может видеть, что параметр никогда не будет равен нулю. В случае SP оптимизатор не может быть уверен, что параметр никогда не будет равен нулю.

Ответ 9

Это, вероятно, маловероятно, но учитывая, что ваше наблюдаемое поведение необычно, его нужно проверять, и никто не упомянул об этом.

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

Просто изредка, когда я видел странное поведение, потому что на самом деле было две копии объекта, и какой из них вы получаете, зависит от того, что указано и кто вы вошли в систему. Например, вполне возможно иметь две копии вида или процедуры с тем же именем, но принадлежащие разным владельцам - ситуация, которая может возникнуть там, где вы не вошли в базу данных в качестве dbo, и забудьте указать dbo как владельца объекта, когда вы создаете объект.

Обратите внимание, что в тексте вы запускаете некоторые вещи без указания владельца, например

sp_recompile ViewOpener

если, например, там, где две копии viewOpener, принадлежащие dbo и [другому пользователю], затем тот, который вы фактически перекомпилируете, если вы не укажете, зависит от обстоятельств. Тоже с представлением Report_Opener - если там, где две копии (и они могут отличаться в спецификации или плане выполнения), то то, что используется, зависит от обстоятельств - и поскольку вы не укажете владельца, вполне возможно, что ваш adhoc-запрос может использовать один и скомпилированная процедура может использовать другую.

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

Ответ 10

Это может показаться глупым и кажется очевидным с именем SessionGUID, но является ли столбец уникальным идентификатором в Report_Opener? Если нет, вы можете попробовать применить его к правильному типу и дать ему снимок или объявить свою переменную правильным типом.

План, созданный как часть sproc, может работать неинтуитивно и делать внутреннюю отливку на большой таблице.

Ответ 11

У меня есть другая идея. Что делать, если вы создаете эту табличную функцию:

CREATE FUNCTION tbfSelectFromView
(   
    -- Add the parameters for the function here
    @SessionGUID UNIQUEIDENTIFIER
)
RETURNS TABLE 
AS
RETURN 
(
    SELECT *
    FROM Report_Opener
    WHERE SessionGUID = @SessionGUID
    ORDER BY CurrencyTypeOrder, Rank
)
GO

И затем выбирается из него, используя следующий оператор (даже помещая его в свой SP):

SELECT *
FROM tbfSelectFromView(@SessionGUID)

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

Ответ 12

У меня была такая же проблема сегодня утром, было очень странно, классическая страница asp, на которой хранится Stored Proc, занимала 1 мин+. SQL-страница asp выполнялась через 2 секунды в MSSMS... Прежде чем тратить возрасты, исследуя планы выполнения, я думал, что просто сделаю небольшое изменение в SP с помощью ALTER PROCEDURE (вставил строку комментария). После запуска инструкции ALTER SP выполняется мгновенно как в IIS, так и в MSSMS. Я предполагаю, что стандартная перекомпиляция SP сделала бы трюк: (удобная информация о перекомпиляции здесь кстати:)

http://www.devx.com/tips/Tip/13386

Ответ 13

Восстановление индексов в соответствующих таблицах помогло мне решить эту проблему

Ответ 14

- Вот решение:

create procedure GetOrderForCustomers(@CustID varchar(20))

as

begin

select * from orders

where customerid = ISNULL(@CustID, '')

end

- Что он

Ответ 15

У меня был похожий опыт работы с IBM DB2, и ответ Адама Маршалла о "перехвате параметров" также помог мне решить проблему.