SQL 2000 UNION ALL рушит оптимизацию запросов - PullRequest
5 голосов
/ 19 мая 2011

У меня есть хранимая процедура, которая занимает менее секунды, чтобы нормально работать.В этом запросе пользователи хотели получить данные из другой таблицы, поэтому я объединил эти данные с UNION ALL и набором фиктивных столбцов, отсутствующих в новой таблице.

В тестировании это работало нормально, но когда мы развернулиэто к SQL 2000 Server, он начал получать тайм-ауты.Старый запрос выполняется менее чем за секунду, а два новых запроса выполняются менее чем за секунду, но когда они объединяются с использованием UNION ALL, время ожидания истекает.

Вот общее представление о том, как выполняется запросвыглядит.Реальный запрос имеет около 20 входных параметров и возвращает около 30 или 40 столбцов, но это должно дать основную идею:

CREATE PROCEDURE dbo.SearchHistory
(
    @Criteria1 bigint,
    @Criteria2 int,
    @Criteria3 varchar(10)
)
AS
BEGIN
    -- Part 1
    SELECT
        A,
        NULL AS B,
        0 AS C,
        D
    FROM TableA
    WHERE @Criteria1 IS NULL
    AND @Criteria3 IS NULL
    AND (A = @Criteria2 OR @Criteria2 IS NULL)

UNION ALL

    -- Part 2
    SELECT
        A,
        NULL AS B,
        0 AS C,
        E
    FROM TableA
    WHERE @Criteria1 IS NULL
    AND @Criteria3 IS NULL
    AND (A = @Criteria2 OR @Criteria2 IS NULL)

UNION ALL

    -- Part 3
    SELECT
        A,
        B,
        C,
        D
    FROM TableB
    WHERE (F = @Criteria1 OR @Criteria1 IS NULL)
    AND (A = @Criteria2 OR @Criteria2 IS NULL)
    AND (G = @Criteria3 OR @Criteria3 IS NULL)
END

В приведенном выше примере @ Criteria1 не является нулевым, поэтому в части 1 и 2вернуть 0 строк, а часть 3 возвращает только 3 строки.Но если я закомментирую Части 1 и 2, это немедленно заканчивается;если я оставлю их, у меня будет тайм-аут.

Как убедить SQL Server не возиться с его планом выполнения в такой ситуации?

Ответы [ 2 ]

3 голосов
/ 19 мая 2011

Я думаю, что ваша проблема из-за перехвата параметров SQL Server.

http://elegantcode.com/2008/05/17/sql-parameter-sniffing-and-what-to-do-about-it/

http://blogs.msdn.com/b/queryoptteam/archive/2006/03/31/565991.aspx

Я встречал это несколько раз.Есть несколько способов обойти это.Например, используйте WITH RECOMPILE, как предложено @Biff MaGriff.Самый простой способ, который я нашел, чтобы исправить это преобразовать все ваши входные параметры в локальные параметры и использовать локальные.

0 голосов
/ 21 мая 2011

На это невозможно ответить, не видя планов выполнения (пожалуйста, опубликуйте их в виде изображений, по одному для каждой части и одно для запроса объединения).Обходной путь - использовать временную таблицу, в которую вы вставляете детали по отдельности.Однако лучшим решением было бы исправить запрос в первую очередь.

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