Sql Server подкачки строк по смещению - без 'ORDER BY' - PullRequest
0 голосов
/ 31 октября 2009

Моя производственная таблица содержит более миллиона записей. Требование требует пейджингового запроса для извлечения записей по параметрам OFFSET и LIMIT (аналогично предложению MySql LIMIT), без сортировки набора результатов, так же, как естественный порядок строк в табличном сканировании, так как ORDER BY генерирует неприемлемую производительность. воздействие, включая предложение «ORDER BY», используемое в традиционной технике ROW_NUMBER () OVER (ORDER BY ...).
Может ли какой-либо эксперт предложить решение этой проблемы? Пейджинговые записи без упорядочения результирующего набора. например,

Create table RandomRecords(int id, datetime recordDate)
----
select * from RandomRecords
34, '1/1/2009'
123, '8/1/2008'
11, '2/23/2008'
10, '3/2/2008'
4, '2/5/2009'
78, '1/1/2008'
55, '5/2/2008'
6666, '2/12/2009'
....
one million rows

-----
paging query with @Offset = 3 and @limit=4 generates
11, '2/23/2008'
10, '3/2/2008'
4, '2/5/2009'
78, '1/1/2008'

Ответы [ 3 ]

3 голосов
/ 31 октября 2009

Это просто комментарий в дополнение к ответу Ремуса.

Пейджинг первичного ключа не приводит к сортировке SQL Server, поскольку первичный ключ хранится в порядке сортировки. Вы можете выполнять поиск по первичному ключу без оператора WITH, например:

SELECT *
FROM (
    SELECT 
        ROW_NUMBER() OVER (ORDER BY PrimaryKey) as rn
    ,   *
    FROM BigTable
) sub 
WHERE sub.rn BETWEEN 3 and 7

Подзапрос все еще требуется, потому что вы не можете использовать ROW_NUMBER () в операторе WHERE.

2 голосов
/ 31 октября 2009

ORDER BY создает дополнительное влияние, только если оно не может быть учтено индексом. Если вы видите «неприемлемое» влияние, это означает, что вы либо неправильно разработали свою таблицу, либо неправильно разработали запрос.

Некоторые используемые нами выражения ORDER BY SELECT ..., ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM .... Но это все равно может привести к появлению сортировочной катушки, если она неправильно спроектирована.

Итак, рассмотрим ваш пример:

CREATE TABLE RandomRecords (recordId int not null primary key, id int);
INSERT INTO RandomRecords (id) values (...)
WITH PagedRandomRecords (
   SELECT id, 
      ROW_NUMBER() OVER (ORDER BY recordId) as rn
      FROM RandomRecords)
SELECT id FROM PagedRandomRecords
   WHERE rn BETWEEN 3 and 7;

Это не сортирует данные, потому что кластерный индекс recordId PK может доставлять строки в нужном порядке.

0 голосов
/ 28 апреля 2016

Если вы все еще не нашли столбец для ORDER BY, вы можете отсортировать по постоянному столбцу, который вы добавили, просто чтобы запрос работал:

SELECT col1, col2 FROM
   (SELECT col1, col2,
      ROW_NUMBER() OVER (ORDER BY alias_sort) AS alias_rownum
   FROM 
      (SELECT col1, col2, 0 AS alias_sort
      FROM 
         (SELECT col1, col2
         FROM ...)))
WHERE alias_rownum >= 12345 AND alias_rownum <= 67890

" 0 AS alias_sort " предоставляет столбец констант, используемый в предложении ORDER BY в родительском запросе. Верхний внешний запрос предоставляет фильтр и избавляет как от суррогатных внутренних столбцов alias_rownum, так и от alias_sort.

...