У мене така таблиця:
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
. Не потрібно повертати його в цьому запиті.