Как ускорить MAX(ID) в секционированной по дате таблице?

Работаю с MS SQL Server. Есть таблица в которой поле ID - это кластеризованный индекс. С фрагментацией индекса всё ок(почти 0%). Таблица секционирована по месяцам. Хочу получить максимальное значение ключа:

SELECT MAX(ID_CONTACT) FROM CMS_Contact_Info

Оптимизатор почему-то решил, что просмотр всей таблицы - это хорошая идея, хотя казалось бы: нужно просто спуститься по дереву кластеризованного индекса к последней странице и на ней найти максимальное значение ключа. Вместо этого он берёт наиболее лёгкий некластеризованный индекс и полностью просматривает его. Если добавить хинт "WITH (INDEX (IDX_ID_CONTACT))", то ситуация ещё хуже. Пробовал и так:

SELECT TOP 1 ID_CONTACT FROM CMS_Contact_Info ORDER BY ID_CONTACT DESC

Всё равно план +/- такой же. Помогите понять в чём я ошибаюсь и как сделать запрос моментальным? План выполнения прилагаю:введите сюда описание изображения


Ответы (1 шт):

Автор решения: Виталий Злобин

Нашёл решение:

SELECT MAX(PARTITION_MAX) AS MAX_ID
FROM
(
    SELECT DISTINCT PARTITION_NUMBER
    FROM sys.partitions
    WHERE object_id = OBJECT_ID('CMS_CONTACT_INFO')
) AS PARTITION_NUMBERS
CROSS APPLY
(
    SELECT MAX(ID_CONTACT) AS PARTITION_MAX
    FROM CMS_CONTACT_INFO
    WHERE $partition.pfMonthsByDatetime2(DT_CONTACT) = PARTITION_NUMBERS.PARTITION_NUMBER
) AS PARTITION_MAX

В первом подзапросе получаем номера всех секций, тут обращение к системному представлению sys.partitions - это быстро. Затем, в CROSS APPLY, находим максимум для каждой секции - это тоже быстро, т.к. таблица отсортирована по ID. В конце, из полученных максимумов каждой секции, находим максимум для всей таблицы.


План запроса стал страшнее, а вот время(4мс против 39 700мс) и количество чтений(470 против 851 550) улучшились многократно:

введите сюда описание изображения

Сергей Олонцев, благодарю за исчерпывающий доклад "Практическое применение секционирования в SQL Server". Не зря MVP по SQL Server)

→ Ссылка