Direct SQL Query против EXEC - PullRequest
       0

Direct SQL Query против EXEC

0 голосов
/ 15 апреля 2011

У меня есть запрос, который выполняется через LINQ to SQL. Запрос выглядит так:

exec sp_executesql N'
SELECT DISTINCT [t2].[ID],...
FROM 
    Table1 AS [t0]
    INNER JOIN Table2 AS [t1] ON [t0].[Table1ID] = [t1].[Table1ID]
    INNER JOIN Table3 AS [t2] ON [t2].[Table2ID] = [t0].[Table2ID]
WHERE 
    ([t2].[Visible] = @p0) 
    AND ([t1].[AncestorID] IN (@p1,...,@p277))',N'@p0 int,...,@p277 int',@p0=1,...@p277=2875

Как видите, это в основном запрос в предложении с 277 параметрами. Используя exec и передавая параметры, как указано выше, запрос занимает 20 секунд .

Если я извлекаю запрос из вызова exec и запускаю его «нормально», это займет меньше , чем одна секунда . Вот запрос:

DECLARE @p0 int;
...
DECLARE @p277 int;

SET @p0=1;
...
SET @p277=287;

SELECT DISTINCT [t2].[ID],...
    FROM 
        Table1 AS [t0]
        INNER JOIN Table2 AS [t1] ON [t0].[Table1ID] = [t1].[Table1ID]
        INNER JOIN Table3 AS [t2] ON [t2].[Table2ID] = [t0].[Table2ID]
    WHERE 
        ([t2].[Visible] = @p0) 
        AND ([t1].[AncestorID] IN (@p1,...,@p277))

Третий тест, когда я заключаю второй запрос в exec, он работает мгновенно все еще. Таким образом, проблема заключается в передаче параметров в вызове exec.

Ответы [ 2 ]

1 голос
/ 16 апреля 2011

Так что проблема, кажется, с передавая параметры в Exec Call.

Я думаю, что у вас почему-то разные планы выполнения.

Вот статья Эрланда Соммарскога, которая может помочь вам выяснить, что происходит.

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

0 голосов
/ 16 апреля 2011

Вероятно, проблема связана с «Обнаружением параметров», и статья, связанная с @Mikael, говорит об этом.К сожалению, это один из основных недостатков использования ORM, поскольку вы теряете возможность настраивать SQL для повышения производительности.

Вот несколько вещей, которые нужно попробовать:

  1. ВыполнитьDBCC FREEPROCCACHE и снова запустите запрос из приложения, чтобы увидеть, есть ли разница.Многократный запуск не даст новый план выполнения, поскольку он уже кэширован с первого запуска.
  2. Обязательно перестройте индексы в таблицах, чтобы убедиться, что статистика актуальна (перестройка,не defrag должен автоматически обновлять статистику)
  3. При необходимости вы всегда можете преобразовать эту операцию в хранимую процедуру и вызывать ее из LINQ-to-SQL.Тогда вам, возможно, придется передать список значений в виде списка через запятую или XML.Если вы используете SQL Server 2008 (или новее), лучшим решением было бы создать DataTable на стороне приложения и передать его в Proc в качестве параметра с табличным значением и использовать его в INNER JOIN вместо списка IN.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...