Очень медленный запрос с TOP и ORDER BY - PullRequest
0 голосов
/ 11 апреля 2019

У меня есть запрос в SQL Server 2014, который требует много времени для получения результатов при его выполнении.

Когда я удаляю вторжения TOP или ORDER BY, он выполняется быстрее, но если я пишу их оба, это занимает много времени.

SELECT TOP (10) A.ColumnValue AS ValueA
FROM TableA AS A
    INNER JOIN TableB AS B
        ON A.ID = B.ID
WHERE A.DateValue > '1982-05-02'
ORDER BY ValueA

Как я могу сделать это быстрее?

Ответы [ 4 ]

2 голосов
/ 11 апреля 2019

Вы говорите

Когда я удаляю TOP или ORDER BY ... он выполняется быстрее

Что означает, что у SQL Server нет проблем с генерацией всего набора результатов в нужном порядке. Это просто идет грушевидной формы с ограничением TOP 10. Это общая проблема с rowgoals . Когда SQL Server знает, что вам нужны только первые несколько результатов, он может выбрать другой план, пытаясь оптимизировать для этого случая, который может иметь неприятные последствия.

Более поздние версии включают подсказку DISABLE_OPTIMIZER_ROWGOAL, чтобы отключить это для каждого запроса. В старых версиях вы можете использовать QUERYTRACEON 4138, как показано ниже.

SELECT TOP (10) A.ColumnValue AS ValueA
FROM TableA AS A
    INNER JOIN TableB AS B
        ON A.ID = B.ID
WHERE A.DateValue > '1982-05-02'
ORDER BY ValueA
OPTION (QUERYTRACEON 4138) 

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

В этом случае вы можете скрыть значение TOP в переменной, как показано ниже

DECLARE @Top INT = 10

SELECT TOP (@Top) A.ColumnValue AS ValueA
FROM TableA AS A
    INNER JOIN TableB AS B
        ON A.ID = B.ID
WHERE A.DateValue > '1982-05-02'
ORDER BY ValueA
option (optimize for (@Top = 1000000))
1 голос
/ 11 апреля 2019

создайте индекс на основе ID столбца обеих таблиц

    CREATE INDEX index_nameA
    ON TableA (ID, DateValue)
;
    CREATE INDEX index_nameB
    ON TableB (ID)

это создаст лучший план во время выполнения запроса

0 голосов
/ 11 апреля 2019

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

Я могу представить лучший план выполнения запроса, сформулированный следующим образом:

SELECT TOP (10) A.ColumnValue AS ValueA
FROM TableA A
WHERE EXISTS (SELECT 1 FROM TableB b WHERE A.ID = B.ID) AND
      A.DateValue > '1982-05-02'
ORDER BY ValueA;

с индексами на TableA(ValueA, DateValue, Id, ColumnValue) и TableB(id). Этот план выполнения будет сканировать индекс с самого начала, а затем выполнить тест на DateValue и Id и вернуть ColumnValue для соответствующих совпадающих строк.

Однако я не думаю, что SQL Server сгенерирует этот план (хотя его стоит попробовать), и я не знаю, как его форсировать, если это не так.

0 голосов
/ 11 апреля 2019

Лучший способ - использовать индексы для повышения производительности.Здесь, в этом случае, индекс может быть включен (date_value).Для использования индексов обратитесь к этому URL: используя индексы

...