Как лучше всего (с точки зрения производительности) разбивать результаты на страницы в SQL Server 2000, 2005, 2008, 2012, если вы также хотите получить общее количество результатов (до разбивки на страницы)?
sql
sql-server
performance
pagination
Панагиотис Коррос
источник
источник
Ответы:
Получение общего количества результатов и разбиение на страницы - это две разные операции. Для примера рассмотрим, что запрос, с которым вы работаете,
В этом случае вы можете определить общее количество результатов, используя:
... который может показаться неэффективным, но на самом деле довольно производительным, при условии, что все индексы и т. д. правильно настроены.
Затем, чтобы получить фактические результаты назад в постраничном виде, следующий запрос будет наиболее эффективным:
Это вернет строки 1-19 исходного запроса. Крутая вещь, особенно для веб-приложений, заключается в том, что вам не нужно сохранять состояние, кроме номеров строк, которые должны быть возвращены.
источник
Наконец, Microsoft SQL Server 2012 был выпущен, мне очень нравится его простота для нумерации страниц, вам не нужно использовать сложные запросы, подобные ответам здесь.
Для получения следующих 10 строк просто запустите этот запрос:
https://docs.microsoft.com/en-us/sql/t-sql/queries/select-order-by-clause-transact-sql#using-offset-and-fetch-to-limit-the-rows- возвращенный
Ключевые моменты, которые следует учитывать при его использовании:
ORDER BY
обязательно использоватьOFFSET ... FETCH
пункт.OFFSET
пункт обязателен сFETCH
. Вы не можете использоватьORDER BY ... FETCH
.TOP
не может быть объединен с однимOFFSET
иFETCH
тем же выражением запроса.источник
LISTAGG()
/GROUP_CONCAT()
.FOR XML
: stackoverflow.com/a/273330/429949FOR XML PATH ('')
. Во-первых, он заменяет управляющие символы XML на коды сущностей XML. Надеюсь , что у вас нет<
,>
или&
в ваших данных! Во-вторых,FOR XML PATH ('')
используемый таким образом фактически недокументированный синтаксис. Вы должны указать именованный столбец или альтернативное имя элемента. Делать ни то, ни другое в документе не означает, что поведение ненадежно. В-третьих, чем больше мы принимаем нарушенныйFOR XML PATH ('')
синтаксис, тем меньше вероятность того, что MS на самом деле предоставляет реальнуюLISTAGG() [ OVER() ]
функцию, в которой они нуждались.Невероятно, но ни в одном другом ответе не упоминается самый быстрый способ разбивки на страницы во всех версиях SQL Server. Смещения могут быть очень медленными для больших номеров страниц, как показано здесь . Существует совершенно другой, гораздо более быстрый способ разбивки на страницы в SQL. Это часто называют «методом поиска» или «разбиением на страницы набора ключей», как описано в этом посте здесь .
Предикат поиска
Значения
@previousScore
и@previousPlayerId
являются соответствующими значениями последней записи с предыдущей страницы. Это позволяет вам получить «следующую» страницу. ЕслиORDER BY
направлениеASC
, просто используйте>
вместо этого.С помощью описанного выше метода вы не можете сразу перейти к странице 4, не предварительно загрузив предыдущие 40 записей. Но часто, вы все равно не хотите прыгать так далеко. Вместо этого вы получаете гораздо более быстрый запрос, который может извлекать данные в постоянное время, в зависимости от вашей индексации. Кроме того, ваши страницы остаются «стабильными», независимо от того, изменяются ли базовые данные (например, на странице 1, пока вы находитесь на странице 4).
Это лучший способ реализовать разбиение на страницы, например, при отложенной загрузке большего количества данных в веб-приложения.
Обратите внимание, что «метод поиска» также называется пагинацией набора ключей .
Всего записей перед нумерацией страниц
Функция
COUNT(*) OVER()
окна поможет вам подсчитать общее количество записей «до нумерации страниц». Если вы используете SQL Server 2000, вам придется прибегнуть к двум запросам дляCOUNT(*)
.источник
OFFSET .. FETCH
или с предыдущимиROW_NUMBER()
приемами.RowNumber
дает мне одинаковые 10 элементов на странице. [3] он не работает с существующими сетками, которые предполагаютpagenumber
иpagesize
.Начиная с SQL Server 2012, мы можем использовать
OFFSET
иFETCH NEXT
пункт для достижения нумерации страниц.Попробуйте это для SQL Server:
TechNet. Пейджинг запросов с помощью SQL Server
источник
MSDN: ROW_NUMBER (Transact-SQL)
источник
На http://www.codeproject.com/KB/aspnet/PagingLarge.aspx вы найдете хороший обзор различных техник подкачки.
Я использовал метод ROWCOUNT довольно часто в основном с SQL Server 2000 (будет работать и с 2005 и 2008 годами, просто измерьте производительность по сравнению с ROW_NUMBER), он молниеносен, но вы должны убедиться, что отсортированные столбцы имеют (в основном ) уникальные ценности.
источник
Для SQL Server 2000 вы можете смоделировать ROW_NUMBER (), используя переменную таблицы со столбцом IDENTITY:
Этот подход можно распространить на таблицы с ключами из нескольких столбцов, и он не влечет за собой снижения производительности при использовании OR (что пропускает использование индекса). Недостатком является количество использованного временного пространства, если набор данных очень большой и один находится рядом с последней страницей. Я не проверял производительность курсора в этом случае, но он мог бы быть лучше.
Обратите внимание, что этот подход может быть оптимизирован для первой страницы данных. Также был использован ROWCOUNT, так как TOP не принимает переменную в SQL Server 2000.
источник
Лучший способ для подкачки страниц в SQL Server 2012 - использовать смещение и выборку следующего в хранимой процедуре. Ключевое слово OFFSET - если мы используем смещение с предложением order by, тогда запрос пропустит количество записей, которое мы указали в OFFSET n Rows.
FETCH NEXT Keywords - когда мы используем Fetch Next только с предложением order by, он возвращает количество строк, которые вы хотите отобразить в подкачке, без Offset, тогда SQL выдаст ошибку. Вот пример, приведенный ниже.
Вы можете выполнить это следующим образом.
источник
Это мои решения для подкачки результатов запроса на стороне сервера SQL. Эти подходы различаются в SQL Server 2008 и 2012. Кроме того, я добавил концепцию фильтрации и упорядочения по одному столбцу. Это очень эффективно, когда вы просматриваете, фильтруете и упорядочиваете в своем Gridview.
Перед тестированием вы должны создать одну примерную таблицу и вставить в нее некоторую строку: (В реальном мире вы должны изменить предложение Where, учитывая ваши поля таблицы, и, возможно, у вас есть несколько соединений и подзапрос в основной части select)
Во всех этих примерах я хочу запросить 200 строк на страницу и извлекаю строку для номера страницы 1200.
В SQL Server 2008 вы можете использовать концепцию CTE. Из-за этого я написал два типа запросов для SQL Server 2008+
- SQL Server 2008+
И второе решение с CTE в SQL Server 2008+
- SQL Server 2012+
источник
Попробуйте этот подход:
источник
В зависимости от случая, следующие, кажется, просты в использовании и быстро. Просто установите номер страницы.
также без CTE
источник
Ну, я использовал следующий пример запроса в моей базе данных SQL 2000, он хорошо работает и для SQL 2005. Мощность, которую он дает, динамически упорядочена с использованием нескольких столбцов. Я говорю вам ... это мощно :)
Лучшая часть - sp_executesql кеширует последующие вызовы, при условии, что вы передаете те же параметры, то есть генерируете тот же текст SQL.
источник
перезапустит idx, когда дело доходит до другого init_id
источник
Для
ROW_NUMBER
техники, если у вас нет сортировочного столбца, вы можете использоватьCURRENT_TIMESTAMP
следующее:Для меня это хорошо сработало при поиске по размерам таблиц даже до 700 000.
Это выбирает записи с 11 до 30.
источник
источник
Этот бит дает возможность разбивать на страницы с использованием SQL Server и более новых версий MySQL и переносит общее количество строк в каждой строке. Использует ваш ключ pimary для подсчета количества уникальных строк.
источник
Это дубликат старого вопроса SO 2012 года: эффективный способ реализации подкачки
Здесь тема обсуждается более подробно и с альтернативными подходами.
источник
С 2012 года мы можем использовать
OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY
источник
Вы не указали ни язык, ни какой драйвер вы используете. Поэтому я описываю это абстрактно.
источник