У меня есть такая таблица:
CREATE TABLE Updates
(
UpdateId INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
ObjectId INT NOT NULL
)
По сути отслеживание обновлений объектов с возрастающим идентификатором.
Потребитель этой таблицы выберет блок из 100 различных идентификаторов объектов, упорядоченных UpdateId
и начиная с определенного UpdateId
. По сути, отслеживание того, где он остановился, и последующий запрос обновлений.
Я обнаружил, что это интересная проблема оптимизации, потому что я смог создать максимально оптимальный план запросов только путем написания запросов, случаются делать то , что я хочу из - за показатели, но не гарантирую , что я хочу:
SELECT DISTINCT TOP 100 ObjectId
FROM Updates
WHERE UpdateId > @fromUpdateId
Где @fromUpdateId
находится параметр хранимой процедуры.
С планом:
SELECT <- TOP <- Hash match (flow distinct, 100 rows touched) <- Index seek
Из-за поиска по используемому UpdateId
индексу результаты уже хороши и упорядочены по убыванию идентификатора обновления, как я хочу. И это порождает особый план, который я хочу. Но порядок заказа явно не гарантируется, поэтому я не хочу его использовать.
Этот трюк также приводит к тому же плану запросов (хотя и с избыточным TOP):
WITH ids AS
(
SELECT ObjectId
FROM Updates
WHERE UpdateId > @fromUpdateId
ORDER BY UpdateId OFFSET 0 ROWS
)
SELECT DISTINCT TOP 100 ObjectId FROM ids
Хотя я не уверен (и не подозреваю), действительно ли это гарантирует порядок.
Я надеялся, что один запрос SQL Server будет достаточно умен, чтобы упростить его, но в итоге получится очень плохой план запроса:
SELECT TOP 100 ObjectId
FROM Updates
WHERE UpdateId > @fromUpdateId
GROUP BY ObjectId
ORDER BY MIN(UpdateId)
С планом:
SELECT <- Top N Sort <- Hash Match aggregate (50,000+ rows touched) <- Index Seek
Я пытаюсь найти способ сгенерировать оптимальный план с поиском по индексу UpdateId
и отдельным потоком для удаления дубликатов ObjectId
s. Есть идеи?
Пример данных, если вы хотите. У объектов редко будет более одного обновления, и почти никогда не должно быть более одного в наборе из 100 строк, поэтому я после отдельного потока , если нет чего-то лучшего, о чем я не знаю? Однако нет гарантии, что в одной ObjectId
таблице не будет более 100 строк. Таблица содержит более 1 000 000 строк и, как ожидается, будет быстро расти.
Предположим, что у пользователя есть другой способ найти подходящее следующее @fromUpdateId
. Нет необходимости возвращать его в этом запросе.