Новая OFFSET ... FETCH
модель, представленная в SQL Server 2012, предлагает простую и быструю подкачку страниц. Почему вообще существуют различия, если учесть, что эти две формы семантически идентичны и очень распространены?
Можно предположить, что оптимизатор распознает оба и оптимизирует их (тривиально) в полной мере.
Вот очень простой случай, когда OFFSET ... FETCH
~ в 2 раза быстрее в соответствии с оценкой стоимости.
SELECT * INTO #objects FROM sys.objects
SELECT *
FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY object_id) r
FROM #objects
) x
WHERE r >= 30 AND r < (30 + 10)
ORDER BY object_id
SELECT *
FROM #objects
ORDER BY object_id
OFFSET 30 ROWS FETCH NEXT 10 ROWS ONLY
Можно изменить этот контрольный пример, создав CI object_id
или добавив фильтры, но удалить все различия планов невозможно. OFFSET ... FETCH
всегда быстрее, потому что он выполняет меньше работы во время выполнения.
Ответы:
Примеры, приведенные в вопросе, не дают одинаковых результатов (в
OFFSET
примере есть ошибка «один за другим»). Обновленные формы ниже исправляют эту проблему, удаляют дополнительную сортировку дляROW_NUMBER
случая и используют переменные, чтобы сделать решение более общим:ROW_NUMBER
План имеет ориентировочную стоимость 0.0197935 :OFFSET
План имеет ориентировочную стоимость 0.0196955 :Это экономит 0,000098 единиц расчетной стоимости (хотя
OFFSET
план потребует дополнительных операторов, если вы хотите вернуть номер строки для каждой строки).OFFSET
План еще будет немного дешевле, вообще говоря, но помните , что сметные расходы именно это - реальное тестирование еще требуется. Большая часть затрат в обоих планах - это стоимость полного набора входных данных, поэтому полезные индексы будут полезны для обоих решений.Если используются постоянные литеральные значения (например,
OFFSET 30
в исходном примере), оптимизатор может использовать сортировку TopN вместо полной сортировки, за которой следует Top. Когда строки, необходимые из сортировки TopN, являются константным литералом и <= 100 (суммаOFFSET
иFETCH
), механизм выполнения может использовать другой алгоритм сортировки, который может работать быстрее, чем обобщенная сортировка TopN. Все три случая имеют разные характеристики производительности в целом.Относительно того, почему оптимизатор не преобразует автоматически используемый
ROW_NUMBER
синтаксический шаблонOFFSET
, существует ряд причин:OFFSET
План не гарантированно будет лучше во всех случаяхОдин пример для третьего пункта выше встречается, когда набор страниц достаточно широк. Гораздо эффективнее искать ключи, необходимые с использованием некластеризованного индекса и поиска вручную по кластерному индексу, по сравнению со сканированием индекса с помощью
OFFSET
илиROW_NUMBER
. Существуют и другие проблемы, которые необходимо учитывать, если приложению подкачки нужно знать, сколько всего строк или страниц. Существует еще одна хорошая дискуссия относительных достоинств «ключ искать» и «смещение» методы здесь .В целом, вероятно, лучше, чтобы люди приняли информированное решение изменить свои пейджинговые запросы для использования
OFFSET
, если это уместно, после тщательного тестирования.источник
С небольшим изменением вашего запроса я получаю равную оценку стоимости (50/50) и равную статистику ввода-вывода:
Это позволяет избежать дополнительной сортировки, которая появляется в вашей версии, сортируя
r
вместоobject_id
.источник
r
а не по основному столбцу, хотя бы потому, что оно совпадает с тем, что я буду делать в не вложенном запросе, и упорядочение по выражению - вместо повторения выражения я бы использовал псевдоним, назначенный выражению.Они изменили оптимизатор запросов для добавления этой функции. Это означает, что они реализовали механизмы специально для поддержки команды offset ... fetch. Другими словами, для верхнего запроса SQL Server должен выполнять гораздо больше работы. Таким образом, разница в планах запросов.
источник