Там какая-либо проблема производительности использует Row_Number для реализации подкачки страниц таблицы в SQL-сервере 2008?

Я хочу реализовать подкачку страниц таблицы с помощью этого метода:

SET @PageNum = 2;
SET @PageSize = 10;

WITH OrdersRN AS
(
    SELECT ROW_NUMBER() OVER(ORDER BY OrderDate, OrderID) AS RowNum
          ,*
      FROM dbo.Orders
)

SELECT * 
  FROM OrdersRN
 WHERE RowNum BETWEEN (@PageNum - 1) * @PageSize + 1 
                  AND @PageNum * @PageSize
 ORDER BY OrderDate ,OrderID;

Есть ли что-нибудь, о чем я должен знать? Таблица имеет миллионы записей.

Спасибо.

Править: После предложенного использования MAXROWS метод в течение некоторого времени (который работает действительно действительно быстро) я должен был переключиться назад на ROW_NUMBER метод из-за его большей гибкости. Я также очень доволен его скоростью до сих пор (я работаю с Представлением, имеющим больше затем 1M записи с 10 столбцами). Для использования любого вида запроса, я использую следующую модификацию:

PROCEDURE [dbo].[PageSelect] 
(
  @Sql nvarchar(512),
  @OrderBy nvarchar(128) = 'Id',
  @PageNum int = 1,
  @PageSize int = 0    
)
AS
BEGIN
SET NOCOUNT ON

 Declare @tsql as nvarchar(1024)
 Declare @i int, @j int

 if (@PageSize <= 0) OR (@PageSize > 10000)
  SET @PageSize = 10000  -- never return more then 10K records

 SET @i = (@PageNum - 1) * @PageSize + 1 
 SET @j = @PageNum * @PageSize

 SET @tsql = 
 'WITH MyTableOrViewRN AS
 (
  SELECT ROW_NUMBER() OVER(ORDER BY ' + @OrderBy + ') AS RowNum
     ,*
    FROM MyTableOrView
    WHERE ' + @Sql  + '

 )
 SELECT * 
  FROM MyTableOrViewRN 
  WHERE RowNum BETWEEN ' + CAST(@i as varchar) + ' AND ' + cast(@j as varchar)

 exec(@tsql)
END

Если Вы используете эту процедуру, удостоверяются, что u предотвратил внедрение SQL.

13
задан majkinetor 1 April 2010 в 08:39
поделиться

3 ответа

Я уже писал об этом несколько раз; ROW_NUMBER , безусловно, самый гибкий и простой в использовании, а производительность хорошая , но для очень больших наборов данных это не всегда лучший . SQL Server все еще нуждается в сортировке данных, и сортировка может оказаться довольно дорогой.

Здесь есть другой подход , который использует пару переменных и SET ROWCOUNT и работает очень быстро при условии, что у вас есть правильные индексы. Он старый, но, насколько я знаю, по-прежнему самый эффективный. По сути, вы можете сделать совершенно наивный SELECT с помощью SET ROWCOUNT , и SQL Server сможет оптимизировать большую часть реальной работы; план и стоимость в конечном итоге аналогичны двум запросам MAX / MIN , что обычно намного быстрее, чем даже один запрос управления окнами. Для очень больших наборов данных это выполняется менее чем за 1/10 времени.

Тем не менее, я всегда рекомендую ROW_NUMBER , когда люди спрашивают о том, как реализовать такие вещи, как разбиение по страницам или групповые максимумы, из-за того, насколько легко это использовать. Я бы начал рассматривать альтернативы, подобные приведенным выше, только если вы начнете замечать замедление с ROW_NUMBER .

19
ответ дан 1 December 2019 в 21:37
поделиться

Недавно я использовал разбиение на страницы в среде хранилища данных со схемой «звезда». Я обнаружил, что производительность была очень хорошей, когда я ограничил CTE запросом только строк, необходимых для определения ROW_NUMBER . Я попросил CTE вернуть ROW_NUMBER плюс первичные ключи других строк, которые помогли определить номер строки.

В основном запросе я сослался на ROW_NUMBER для разбиения на страницы, а затем присоединился к другим таблицам на основе других первичных ключей из CTE. Я обнаружил, что соединения выполнялись только в тех строках, которые удовлетворяли условию WHERE во внешнем запросе, что сэкономило много времени.

8
ответ дан 1 December 2019 в 21:37
поделиться

У вас нет параметров компилятора C++, пока вы не используете компилятор C++. В этом случае у вас нет файла .cpp. Поэтому просто добавьте один и появятся параметры компилятора.

-121--2789776-

Макросы (определения) могут использоваться препроцессором, а во время компиляции константы не могут.

Можно выполнить проверку времени компиляции, чтобы убедиться, что макрос находится в допустимом диапазоне (и # error или # fatal, если это не так). Можно использовать значения по умолчанию для макроса, если он еще не определен. Макрос можно использовать в размере массива.

Компилятор может оптимизировать с помощью макросов лучше, чем с помощью констант:

const int SIZE_A = 15;
#define SIZE_B 15

for (i = 0; i < SIZE_A + 1; ++i);    // if not optimized may load A and add 1 on each pass
for (i = 0; i < SIZE_B + 1; ++i);    // compiler will replace "SIZE_B + 1" with 16

Большая часть моей работы связана со встроенными процессорами, которые не имеют удивительных оптимизирующих компиляторов. Может быть, gcc будет относиться к SIZE_A как к макросу на каком-то уровне оптимизации.

-121--1109255-

протестировать это решение, может быть, оно лучше. Измените это с вашей потребностью, пожалуйста.

CREATE PROCEDURE sp_PagedItems
    (
     @Page int,
     @RecsPerPage int
    )
AS

-- We don't want to return the # of rows inserted
-- into our temporary table, so turn NOCOUNT ON
SET NOCOUNT ON


--Create a temporary table
CREATE TABLE #TempItems
(
    ID int IDENTITY,
    Name varchar(50),
    Price currency
)


-- Insert the rows from tblItems into the temp. table
INSERT INTO #TempItems (Name, Price)
SELECT Name,Price FROM tblItem ORDER BY Price

-- Find out the first and last record we want
DECLARE @FirstRec int, @LastRec int
SELECT @FirstRec = (@Page - 1) * @RecsPerPage
SELECT @LastRec = (@Page * @RecsPerPage + 1)

-- Now, return the set of paged records, plus, an indiciation of we
-- have more records or not!
SELECT *,
       MoreRecords =
    (
     SELECT COUNT(*)
     FROM #TempItems TI
     WHERE TI.ID >= @LastRec
    )
FROM #TempItems
WHERE ID > @FirstRec AND ID < @LastRec


-- Turn NOCOUNT back OFF
SET NOCOUNT OFF
-2
ответ дан 1 December 2019 в 21:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: