Низкая производительность в запросе UPDATE на основе SELECT TOP 1 - PullRequest
0 голосов
/ 29 мая 2018

Я пытаюсь повысить производительность запроса, выполнение которого занимает много времени, и буду признателен за любые указания на то, что мне нужно сделать по-другому, чтобы довести производительность до разумного.(Информация об индексе и приблизительном плане выполнения приведена ниже.)

В обновляемой таблице table1 содержится менее 1000 записей, но в запрашиваемой таблице есть что-то в диапазоне 100 миллионов.Странно, что я использую почти один и тот же запрос для самых старых и самых последних значений, но запрос для самого последнего значения возвращается через две секунды.Это запрос для самого старого значения;для запуска требуется более двух минут:

UPDATE table1
SET firstVal = (
                    SELECT TOP 1 val 
                    FROM table2 
                    WHERE table1.ID = ID
                    AND valID = 123
                    ORDER BY entryDate
                    )

Запрос самой последней, возвращается через две секунды:

UPDATE table1
SET lastVal = (
                    SELECT TOP 1 val 
                    FROM table2  
                    WHERE table1.ID = ID
                    AND valID = 123
                    ORDER BY entryDate DESC
                    )

Индекс:

CREATE NONCLUSTERED INDEX [table2_IX9] ON [dbo].[table2]
(
    [valID] ASC,
    [entryDate] ASC,
    [ID] ASC
)
INCLUDE (   [val]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [AB]
GO

Поиск по индексу(NonClustered) Стоимость: 68%
Максимальная стоимость: 29%

Можно ли сформулировать этот запрос лучше для оптимизации?Есть ли что-то, что мне нужно по-другому на стороне индекса?Заранее спасибо за любое руководство!

Ответы [ 2 ]

0 голосов
/ 29 мая 2018

Что я в итоге сделал:

SELECT ID, val, entryDate
INTO #tmpT2
FROM table2 
WHERE ID IN (SELECT ID FROM table1)
AND valID = 123

А затем с небольшими изменениями, замените # tmpT2 для table2 в исходном запросе:

UPDATE table1
SET firstVal = (
                    SELECT TOP 1 val 
                    FROM #tmpT2 
                    WHERE table1.ID = ID
                    ORDER BY entryDate
                    )

Почему: только что понял, что синдексирование на месте выглядит точно так, как казалось, и таблица1 настолько мала, что я могу просто попытаться использовать временную таблицу и извлечь все идентификаторы, vals и entryDates для valID = 123 во временную таблицу.Этот шаг занял одну секунду, и использование исходного запроса было мгновенным.Спасибо, что нашли время, чтобы обдумать эту проблему и предложить идеи!

0 голосов
/ 29 мая 2018

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

UPDATE T1
SET firstVal = T2.val
FROM Table1 T1
     --This might need to be an OUTER APPLY, but impossible to tell from your post
     CROSS APPLY (SELECT TOP 1 ca.val
                  FROM Table2 ca
                  WHERE ca.ID = T1.ID
                    AND ca.valID = 123
                  ORDER BY ca.entryDate) T2;

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

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