Я хочу реализовать подкачку страниц таблицы с помощью этого метода:
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.
Я уже писал об этом несколько раз; ROW_NUMBER
, безусловно, самый гибкий и простой в использовании, а производительность хорошая , но для очень больших наборов данных это не всегда лучший . SQL Server все еще нуждается в сортировке данных, и сортировка может оказаться довольно дорогой.
Здесь есть другой подход , который использует пару переменных и SET ROWCOUNT
и работает очень быстро при условии, что у вас есть правильные индексы. Он старый, но, насколько я знаю, по-прежнему самый эффективный. По сути, вы можете сделать совершенно наивный SELECT
с помощью SET ROWCOUNT
, и SQL Server сможет оптимизировать большую часть реальной работы; план и стоимость в конечном итоге аналогичны двум запросам MAX
/ MIN
, что обычно намного быстрее, чем даже один запрос управления окнами. Для очень больших наборов данных это выполняется менее чем за 1/10 времени.
Тем не менее, я всегда рекомендую ROW_NUMBER
, когда люди спрашивают о том, как реализовать такие вещи, как разбиение по страницам или групповые максимумы, из-за того, насколько легко это использовать. Я бы начал рассматривать альтернативы, подобные приведенным выше, только если вы начнете замечать замедление с ROW_NUMBER
.
Недавно я использовал разбиение на страницы в среде хранилища данных со схемой «звезда». Я обнаружил, что производительность была очень хорошей, когда я ограничил CTE запросом только строк, необходимых для определения ROW_NUMBER
. Я попросил CTE вернуть ROW_NUMBER
плюс первичные ключи других строк, которые помогли определить номер строки.
В основном запросе я сослался на ROW_NUMBER
для разбиения на страницы, а затем присоединился к другим таблицам на основе других первичных ключей из CTE. Я обнаружил, что соединения выполнялись только в тех строках, которые удовлетворяли условию WHERE
во внешнем запросе, что сэкономило много времени.
У вас нет параметров компилятора 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