sql #sql-server #tsql
#sql #sql-сервер #tsql
Вопрос:
В настоящее время у меня есть этот запрос (SQL Server):
DECLARE @PageNum int = 1;
DECLARE @PageSize int = 2;
SELECT *
FROM (
SELECT *,ROW_NUMBER() OVER(PARTITION BY Color ORDER BY Name) AS Row
FROM Orders
) t1
WHERE Row BETWEEN ((@PageNum-1)*@PageSize 1) AND (@PageNum*@PageSize)
ORDER BY Color,Name
Что делает этот запрос, так это выбирает «страницы» с 2 записями для каждого Color
. Значение, если таблица содержит:
ID | Цвет | Имя |
---|---|---|
1 | Красный | Статья №1 |
2 | Красный | Статья №2 |
3 | Красный | Статья №3 |
4 | Зеленый | Статья №4 |
5 | Зеленый | Статья №5 |
6 | Зеленый | Статья №6 |
7 | Зеленый | Статья №7 |
Тогда приведенный выше запрос приведет к:
ID | Цвет | Имя |
---|---|---|
1 | Красный | Статья №1 |
2 | Красный | Статья №2 |
4 | Зеленый | Статья №4 |
5 | Зеленый | Статья №5 |
На странице 1 и
ID | Цвет | Имя |
---|---|---|
3 | Красный | Статья №3 |
6 | Зеленый | Статья №6 |
7 | Зеленый | Статья №7 |
На странице 2.
Это работает. Однако в моем реальном примере выполнение этого запроса занимает очень много времени — фактически около 10 минут. У меня есть статическая таблица с более чем 800 тыс. записей, которая никогда не меняется. Поскольку эта таблица никогда не меняется, я создал индекс для каждого столбца, по которому я бы фильтровал / сортировал. В этой таблице также есть столбец RowId
, который практически является просто номером строки, и он имеет уникальный индекс.
План выполнения можно увидеть здесь: https://www.brentozar.com/pastetheplan/?id=BkeWfVCSY
Что я могу сделать, чтобы ускорить этот запрос?
Комментарии:
1. Также похоже, что вы изобретаете
LIMIT
иOFFSET
. Пока вы используете 2012 или более позднюю версию, вам не нужно этого делать. Я видел, что некоторые очень плохие планы улучшаются сLIMIT
помощью andOFFSET
.2. @DaleK Я обновил свой вопрос. Спасибо, что указали на это
3. @Mitch Согласно плану выполнения, похоже, что проблема не в этом. Даже если я оставлю предложение WHERE, ничего не изменится.
4. Вам нужен индекс для
[OrderType] desc, [From] asc
или[OrderType] asc, [From] DESC
, чтобы избавиться от операции сортировки.5. вы пробовали
OFFSET/FETCH
? Возможно, вы захотите посмотреть разбивку на страницы набора ключей , которая намного эффективнее, чем разбивка на страницы набора строк, которую вы выполняете.
Ответ №1:
Первая операция в вашем плане выполнения — это сканирование таблицы, поэтому я предполагаю, что это таблица кучи (в противном случае мы должны увидеть сканирование кластеризованного индекса), и созданные вами индексы не используются.
Кроме того, поскольку это статическая таблица, которая никогда не изменяется, согласно описанию, фрагментация не должна быть проблемой.
У меня на этом компьютере не установлен SQL Server, поэтому я не могу сравнить планы выполнения до и после, но я считаю, что для вашего запроса мы можем увидеть некоторые улучшения с кластеризованным индексом, упорядочивая ключи, как предлагает Мартин Смит в своем комментарии.
CREATE CLUSTERED INDEX IX_Order ON dbo.Order(OrderType ASC, From DESC)
Пожалуйста, дайте мне знать, если это улучшит ваш запрос. Если нет, я могу создать аналогичный сценарий для тестирования в течение дня.