在SQL Server中分页结果的最佳方法是什么?

如果您还想获得结果总数(在分页之前),在SQL Server 2000,2005,2008,2012中对结果进行分页的最佳方式(性能明智)是什么?

获得结果总数和分页是两个不同的操作。 为了这个例子,我们假设你正在处理的查询是

SELECT * FROM Orders WHERE OrderDate >= '1980-01-01' ORDER BY OrderDate 

在这种情况下,您可以使用以下方法确定结果总数:

 SELECT COUNT(*) FROM Orders WHERE OrderDate >= '1980-01-01' 

…这看起来效率不高,但实际上是非常高效的,假设所有索引等都正确设置。

接下来,为了以分页方式获得实际结果,以下查询将是最有效的:

 SELECT * FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY OrderDate ) AS RowNum, * FROM Orders WHERE OrderDate >= '1980-01-01' ) AS RowConstrainedResult WHERE RowNum >= 1 AND RowNum < 20 ORDER BY RowNum 

这将返回原始查询的1-19行。 这里很酷的事情,尤其是networking应用程序,你不必保持任何状态,除了要返回的行号。

我也很好奇微软为什么不支持在MySQL或PostgreSQL中使用offset/limit简单查询。 最后,发布Microsoft SQL Server 2012 ,我真的很喜欢它的分页简单性,你不必使用像这里回答的复杂查询。

为了获得下一个10行只是运行这个查询:

 SELECT * FROM TableName ORDER BY id OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY; 

http://technet.microsoft.com/en-us/library/gg699618.aspx

使用它时要考虑的要点:

  • ORDER BY必须使用OFFSET和FETCH子句。
  • FETCH必须使用OFFSET子句。 你永远不能使用ORDER BY … FETCH。
  • 在相同的查询expression式中,TOP不能与OFFSET和FETCH组合。

令人难以置信的是,没有其他答案提到了在所有SQL Server版本中进行分页的最快方法。 按照此处的基准,偏移对于大页面数可能非常缓慢。 在SQL中执行分页有一个完全不同的,更快的方法。 这通常被称为这里的博客文章中描述的“寻找方法”或“键集分页”。

 SELECT TOP 10 first_name, last_name, score, COUNT(*) OVER() FROM players WHERE (score < @previousScore) OR (score = @previousScore AND player_id < @previousPlayerId) ORDER BY score DESC, player_id DESC 

“求谓”

@previousScore@previousPlayerId值是来自上一页的最后一条logging的相应值。 这使您可以获取“下一个”页面。 如果ORDER BY方向是ASC ,只需使用>代替。

用上面的方法,你不能马上跳到第4页而没有先取得前面的40条logging。 但是,往往你不想跳得那么远。 相反,你会得到一个更快的查询,可能能够在固定时间获取数据,这取决于你的索引。 此外,无论基础数据是否更改(例如,第1页,而第4页),您的页面仍保持“稳定”状态。

例如,当在Web应用程序中延迟加载更多数据时,这是实现分页的最佳方式。

请注意,“查找方法”也称为键集分页 。

分页之前的总logging

COUNT(*) OVER()窗口function将帮助您计算“分页之前”的logging总数。 如果您使用的是SQL Server 2000,则必须对COUNT(*)进行两次查询。

http://www.codeproject.com/KB/aspnet/PagingLarge.aspx有不同的分页技术的概述;

我经常使用ROWCOUNT方法,主要是使用SQL Server 2000(也可以和2005和2008一起工作,只是测量性能与ROW_NUMBER相比),它闪电般快,但是您需要确保已sorting的列(大部分)独特的价值。

MSDN:ROW_NUMBER(Transact-SQL)

返回结果集分区内的行的序号,从1开始,为每个分区中的第一行。

以下示例按OrderDate的顺序返回数字为50到60的行。

 WITH OrderedOrders AS ( SELECT ROW_NUMBER() OVER(ORDER BY FirstName DESC) AS RowNumber, FirstName, LastName, ROUND(SalesYTD,2,1) AS "Sales YTD" FROM [dbo].[vSalesPerson] ) SELECT RowNumber, FirstName, LastName, Sales YTD FROM OrderedOrders WHERE RowNumber > 50 AND RowNumber < 60; 
  RowNumber FirstName LastName SalesYTD --- ----------- ---------------------- ----------------- 1 Linda Mitchell 4251368.54 2 Jae Pak 4116871.22 3 Michael Blythe 3763178.17 4 Jillian Carson 3189418.36 5 Ranjit Varkey Chudukatil 3121616.32 6 José Saraiva 2604540.71 7 Shu Ito 2458535.61 8 Tsvi Reiter 2315185.61 9 Rachel Valdez 1827066.71 10 Tete Mensa-Annan 1576562.19 11 David Campbell 1573012.93 12 Garrett Vargas 1453719.46 13 Lynn Tsoflias 1421810.92 14 Pamela Ansman-Wolfe 1352577.13 

从SQL Server 2012开始,我们可以使用OFFSETFETCH NEXT子句来实现分页。

试试这个,对于SQL Server:

在SQL Server 2012中,在ORDER BY子句中添加了一项新function,用于查询集合数据的优化,使用T-SQL编写的数据分页以及SQL Server中的整个执行计划的工作更轻松。

在前面的例子中使用相同逻辑的T-SQL脚本之下。

 --CREATING A PAGING WITH OFFSET and FETCH clauses IN "SQL SERVER 2012" DECLARE @PageNumber AS INT, @RowspPage AS INT SET @PageNumber = 2 SET @RowspPage = 10 SELECT ID_EXAMPLE, NM_EXAMPLE, DT_CREATE FROM TB_EXAMPLE ORDER BY ID_EXAMPLE OFFSET ((@PageNumber - 1) * @RowspPage) ROWS FETCH NEXT @RowspPage ROWS ONLY; 

TechNet:使用SQL Server分页查询

对于SQL Server 2000,您可以使用具有IDENTITY列的表variables来模拟ROW_NUMBER():

 DECLARE @pageNo int -- 1 based DECLARE @pageSize int SET @pageNo = 51 SET @pageSize = 20 DECLARE @firstRecord int DECLARE @lastRecord int SET @firstRecord = (@pageNo - 1) * @pageSize + 1 -- 1001 SET @lastRecord = @firstRecord + @pageSize - 1 -- 1020 DECLARE @orderedKeys TABLE ( rownum int IDENTITY NOT NULL PRIMARY KEY CLUSTERED, TableKey int NOT NULL ) SET ROWCOUNT @lastRecord INSERT INTO @orderedKeys (TableKey) SELECT ID FROM Orders WHERE OrderDate >= '1980-01-01' ORDER BY OrderDate SET ROWCOUNT 0 SELECT t.* FROM Orders t INNER JOIN @orderedKeys o ON o.TableKey = t.ID WHERE o.rownum >= @firstRecord ORDER BY o.rownum 

这种方法可以扩展到具有多列键的表,并且不会导致使用OR(跳过索引使用)的性能开销。 不足之处在于,如果数据集非常大,而且一个在最后一页附近,则会使用临时空间。 在这种情况下,我没有testing光标性能,但可能会更好。

请注意,这种方法可以针对数据的第一页进行优化。 此外,由于TOP不接受SQL Server 2000中的variables,因此使用了ROWCOUNT。

尝试这种方法:

 SELECT TOP @offset a.* FROM (select top @limit b.*, COUNT(*) OVER() totalrows from TABLENAME b order by id asc) a ORDER BY id desc; 

使用案例明智以下似乎易于使用和快速只需设置页码。

 use AdventureWorks DECLARE @RowsPerPage INT = 10, @PageNumber INT = 6; with result as( SELECT SalesOrderDetailID, SalesOrderID, ProductID, ROW_NUMBER() OVER (ORDER BY SalesOrderDetailID) AS RowNum FROM Sales.SalesOrderDetail where 1=1 ) select SalesOrderDetailID, SalesOrderID, ProductID from result WHERE result.RowNum BETWEEN ((@PageNumber-1)*@RowsPerPage)+1 AND @RowsPerPage*(@PageNumber) 

也与CTE

 use AdventureWorks DECLARE @RowsPerPage INT = 10, @PageNumber INT = 6 SELECT SalesOrderDetailID, SalesOrderID, ProductID FROM ( SELECT SalesOrderDetailID, SalesOrderID, ProductID, ROW_NUMBER() OVER (ORDER BY SalesOrderDetailID) AS RowNum FROM Sales.SalesOrderDetail where 1=1 ) AS SOD WHERE SOD.RowNum BETWEEN ((@PageNumber-1)*@RowsPerPage)+1 AND @RowsPerPage*(@PageNumber) 

那么我在我的SQL 2000数据库中使用了下面的示例查询,它也适用于SQL 2005。 它给你的力量是通过使用多列dynamicsorting的。 我告诉你…这是强大的:)

  ALTER PROCEDURE [dbo].[RE_ListingReports_SelectSummary] @CompanyID int, @pageNumber int, @pageSize int, @sort varchar(200) AS DECLARE @sql nvarchar(4000) DECLARE @strPageSize nvarchar(20) DECLARE @strSkippedRows nvarchar(20) DECLARE @strFields nvarchar(4000) DECLARE @strFilter nvarchar(4000) DECLARE @sortBy nvarchar(4000) DECLARE @strFrom nvarchar(4000) DECLARE @strID nvarchar(100) If(@pageNumber < 0) SET @pageNumber = 1 SET @strPageSize = CAST(@pageSize AS varchar(20)) SET @strSkippedRows = CAST(((@pageNumber - 1) * @pageSize) AS varchar(20))-- For example if pageNumber is 5 pageSize is 10, then SkippedRows = 40. SET @strID = 'ListingDbID' SET @strFields = 'ListingDbID, ListingID, [ExtraRoom] ' SET @strFrom = ' vwListingSummary ' SET @strFilter = ' WHERE CompanyID = ' + CAST(@CompanyID As varchar(20)) End SET @sortBy = '' if(len(ltrim(rtrim(@sort))) > 0) SET @sortBy = ' Order By ' + @sort -- Total Rows Count SET @sql = 'SELECT Count(' + @strID + ') FROM ' + @strFROM + @strFilter EXEC sp_executesql @sql --// This technique is used in a Single Table pagination SET @sql = 'SELECT ' + @strFields + ' FROM ' + @strFROM + ' WHERE ' + @strID + ' IN ' + ' (SELECT TOP ' + @strPageSize + ' ' + @strID + ' FROM ' + @strFROM + @strFilter + ' AND ' + @strID + ' NOT IN ' + ' (SELECT TOP ' + @strSkippedRows + ' ' + @strID + ' FROM ' + @strFROM + @strFilter + @SortBy + ') ' + @SortBy + ') ' + @SortBy Print @sql EXEC sp_executesql @sql 

最好的部分是sp_executesqlcaching后来的调用,只要你传递相同的参数,即生成相同的SQL文本。

  CREATE view vw_sppb_part_listsource as select row_number() over (partition by sppb_part.init_id order by sppb_part.sppb_part_id asc ) as idx, * from ( select part.SPPB_PART_ID , 0 as is_rev , part.part_number , part.init_id from t_sppb_init_part part left join t_sppb_init_partrev prev on ( part.SPPB_PART_ID = prev.SPPB_PART_ID ) where prev.SPPB_PART_ID is null union select part.SPPB_PART_ID , 1 as is_rev , prev.part_number , part.init_id from t_sppb_init_part part inner join t_sppb_init_partrev prev on ( part.SPPB_PART_ID = prev.SPPB_PART_ID ) ) sppb_part 

将涉及到不同的init_id重新启动idx

这些是我在SQL服务器端分页查询结果的解决scheme。 这些方法在SQL Server 2008和2012之间是不同的。另外,我添加了一列过滤和sorting的概念。 当你在GridView中进行分页和过滤和sorting的时候,它是非常高效的。

在testing之前,您必须创build一个样本表并在该表中插入一些行(在现实世界中,必须考虑您的表字段更改Where子句,也许在select的主要部分中有一些联接和子查询)

 Create Table VLT ( ID int IDentity(1,1), Name nvarchar(50), Tel Varchar(20) ) GO Insert INTO VLT VALUES ('NAME' + Convert(varchar(10),@@identity),'FAMIL' + Convert(varchar(10),@@identity)) GO 500000 

在所有这些示例中,我想每页查询200行,并且正在获取页码1200的行。

在SQL Server 2008中,您可以使用CTE概念。 因此,我写了SQL Server 2008+的两种types的查询

– SQL Server 2008+

 DECLARE @PageNumber Int = 1200 DECLARE @PageSize INT = 200 DECLARE @SortByField int = 1 --The field used for sort by DECLARE @SortOrder nvarchar(255) = 'ASC' --ASC or DESC DECLARE @FilterType nvarchar(255) = 'None' --The filter type, as defined on the client side (None/Contain/NotContain/Match/NotMatch/True/False/) DECLARE @FilterValue nvarchar(255) = '' --The value the user gave for the filter DECLARE @FilterColumn int = 1 --The column to wich the filter is applied, represents the column number like when we send the information. SELECT Data.ID, Data.Name, Data.Tel FROM ( SELECT ROW_NUMBER() OVER( ORDER BY CASE WHEN @SortByField = 1 AND @SortOrder = 'ASC' THEN VLT.ID END ASC, CASE WHEN @SortByField = 1 AND @SortOrder = 'DESC' THEN VLT.ID END DESC, CASE WHEN @SortByField = 2 AND @SortOrder = 'ASC' THEN VLT.Name END ASC, CASE WHEN @SortByField = 2 AND @SortOrder = 'DESC' THEN VLT.Name END ASC, CASE WHEN @SortByField = 3 AND @SortOrder = 'ASC' THEN VLT.Tel END ASC, CASE WHEN @SortByField = 3 AND @SortOrder = 'DESC' THEN VLT.Tel END ASC ) AS RowNum ,* FROM VLT WHERE ( -- We apply the filter logic here CASE WHEN @FilterType = 'None' THEN 1 -- Name column filter WHEN @FilterType = 'Contain' AND @FilterColumn = 1 AND ( -- In this case, when the filter value is empty, we want to show everything. VLT.ID LIKE '%' + @FilterValue + '%' OR @FilterValue = '' ) THEN 1 WHEN @FilterType = 'NotContain' AND @FilterColumn = 1 AND ( -- In this case, when the filter value is empty, we want to show everything. VLT.ID NOT LIKE '%' + @FilterValue + '%' OR @FilterValue = '' ) THEN 1 WHEN @FilterType = 'Match' AND @FilterColumn = 1 AND VLT.ID = @FilterValue THEN 1 WHEN @FilterType = 'NotMatch' AND @FilterColumn = 1 AND VLT.ID <> @FilterValue THEN 1 -- Name column filter WHEN @FilterType = 'Contain' AND @FilterColumn = 2 AND ( -- In this case, when the filter value is empty, we want to show everything. VLT.Name LIKE '%' + @FilterValue + '%' OR @FilterValue = '' ) THEN 1 WHEN @FilterType = 'NotContain' AND @FilterColumn = 2 AND ( -- In this case, when the filter value is empty, we want to show everything. VLT.Name NOT LIKE '%' + @FilterValue + '%' OR @FilterValue = '' ) THEN 1 WHEN @FilterType = 'Match' AND @FilterColumn = 2 AND VLT.Name = @FilterValue THEN 1 WHEN @FilterType = 'NotMatch' AND @FilterColumn = 2 AND VLT.Name <> @FilterValue THEN 1 -- Tel column filter WHEN @FilterType = 'Contain' AND @FilterColumn = 3 AND ( -- In this case, when the filter value is empty, we want to show everything. VLT.Tel LIKE '%' + @FilterValue + '%' OR @FilterValue = '' ) THEN 1 WHEN @FilterType = 'NotContain' AND @FilterColumn = 3 AND ( -- In this case, when the filter value is empty, we want to show everything. VLT.Tel NOT LIKE '%' + @FilterValue + '%' OR @FilterValue = '' ) THEN 1 WHEN @FilterType = 'Match' AND @FilterColumn = 3 AND VLT.Tel = @FilterValue THEN 1 WHEN @FilterType = 'NotMatch' AND @FilterColumn = 3 AND VLT.Tel <> @FilterValue THEN 1 END ) = 1 ) AS Data WHERE Data.RowNum > @PageSize * (@PageNumber - 1) AND Data.RowNum <= @PageSize * @PageNumber ORDER BY Data.RowNum GO 

而SQL Server 2008+中的第二个CTE解决scheme

 DECLARE @PageNumber Int = 1200 DECLARE @PageSize INT = 200 DECLARE @SortByField int = 1 --The field used for sort by DECLARE @SortOrder nvarchar(255) = 'ASC' --ASC or DESC DECLARE @FilterType nvarchar(255) = 'None' --The filter type, as defined on the client side (None/Contain/NotContain/Match/NotMatch/True/False/) DECLARE @FilterValue nvarchar(255) = '' --The value the user gave for the filter DECLARE @FilterColumn int = 1 --The column to wich the filter is applied, represents the column number like when we send the information. ;WITH Data_CTE AS ( SELECT ROW_NUMBER() OVER( ORDER BY CASE WHEN @SortByField = 1 AND @SortOrder = 'ASC' THEN VLT.ID END ASC, CASE WHEN @SortByField = 1 AND @SortOrder = 'DESC' THEN VLT.ID END DESC, CASE WHEN @SortByField = 2 AND @SortOrder = 'ASC' THEN VLT.Name END ASC, CASE WHEN @SortByField = 2 AND @SortOrder = 'DESC' THEN VLT.Name END ASC, CASE WHEN @SortByField = 3 AND @SortOrder = 'ASC' THEN VLT.Tel END ASC, CASE WHEN @SortByField = 3 AND @SortOrder = 'DESC' THEN VLT.Tel END ASC ) AS RowNum ,* FROM VLT WHERE ( -- We apply the filter logic here CASE WHEN @FilterType = 'None' THEN 1 -- Name column filter WHEN @FilterType = 'Contain' AND @FilterColumn = 1 AND ( -- In this case, when the filter value is empty, we want to show everything. VLT.ID LIKE '%' + @FilterValue + '%' OR @FilterValue = '' ) THEN 1 WHEN @FilterType = 'NotContain' AND @FilterColumn = 1 AND ( -- In this case, when the filter value is empty, we want to show everything. VLT.ID NOT LIKE '%' + @FilterValue + '%' OR @FilterValue = '' ) THEN 1 WHEN @FilterType = 'Match' AND @FilterColumn = 1 AND VLT.ID = @FilterValue THEN 1 WHEN @FilterType = 'NotMatch' AND @FilterColumn = 1 AND VLT.ID <> @FilterValue THEN 1 -- Name column filter WHEN @FilterType = 'Contain' AND @FilterColumn = 2 AND ( -- In this case, when the filter value is empty, we want to show everything. VLT.Name LIKE '%' + @FilterValue + '%' OR @FilterValue = '' ) THEN 1 WHEN @FilterType = 'NotContain' AND @FilterColumn = 2 AND ( -- In this case, when the filter value is empty, we want to show everything. VLT.Name NOT LIKE '%' + @FilterValue + '%' OR @FilterValue = '' ) THEN 1 WHEN @FilterType = 'Match' AND @FilterColumn = 2 AND VLT.Name = @FilterValue THEN 1 WHEN @FilterType = 'NotMatch' AND @FilterColumn = 2 AND VLT.Name <> @FilterValue THEN 1 -- Tel column filter WHEN @FilterType = 'Contain' AND @FilterColumn = 3 AND ( -- In this case, when the filter value is empty, we want to show everything. VLT.Tel LIKE '%' + @FilterValue + '%' OR @FilterValue = '' ) THEN 1 WHEN @FilterType = 'NotContain' AND @FilterColumn = 3 AND ( -- In this case, when the filter value is empty, we want to show everything. VLT.Tel NOT LIKE '%' + @FilterValue + '%' OR @FilterValue = '' ) THEN 1 WHEN @FilterType = 'Match' AND @FilterColumn = 3 AND VLT.Tel = @FilterValue THEN 1 WHEN @FilterType = 'NotMatch' AND @FilterColumn = 3 AND VLT.Tel <> @FilterValue THEN 1 END ) = 1 ) SELECT Data.ID, Data.Name, Data.Tel FROM Data_CTE AS Data WHERE Data.RowNum > @PageSize * (@PageNumber - 1) AND Data.RowNum <= @PageSize * @PageNumber ORDER BY Data.RowNum 

– SQL Server 2012+

 DECLARE @PageNumber Int = 1200 DECLARE @PageSize INT = 200 DECLARE @SortByField int = 1 --The field used for sort by DECLARE @SortOrder nvarchar(255) = 'ASC' --ASC or DESC DECLARE @FilterType nvarchar(255) = 'None' --The filter type, as defined on the client side (None/Contain/NotContain/Match/NotMatch/True/False/) DECLARE @FilterValue nvarchar(255) = '' --The value the user gave for the filter DECLARE @FilterColumn int = 1 --The column to wich the filter is applied, represents the column number like when we send the information. ;WITH Data_CTE AS ( SELECT * FROM VLT WHERE ( -- We apply the filter logic here CASE WHEN @FilterType = 'None' THEN 1 -- Name column filter WHEN @FilterType = 'Contain' AND @FilterColumn = 1 AND ( -- In this case, when the filter value is empty, we want to show everything. VLT.ID LIKE '%' + @FilterValue + '%' OR @FilterValue = '' ) THEN 1 WHEN @FilterType = 'NotContain' AND @FilterColumn = 1 AND ( -- In this case, when the filter value is empty, we want to show everything. VLT.ID NOT LIKE '%' + @FilterValue + '%' OR @FilterValue = '' ) THEN 1 WHEN @FilterType = 'Match' AND @FilterColumn = 1 AND VLT.ID = @FilterValue THEN 1 WHEN @FilterType = 'NotMatch' AND @FilterColumn = 1 AND VLT.ID <> @FilterValue THEN 1 -- Name column filter WHEN @FilterType = 'Contain' AND @FilterColumn = 2 AND ( -- In this case, when the filter value is empty, we want to show everything. VLT.Name LIKE '%' + @FilterValue + '%' OR @FilterValue = '' ) THEN 1 WHEN @FilterType = 'NotContain' AND @FilterColumn = 2 AND ( -- In this case, when the filter value is empty, we want to show everything. VLT.Name NOT LIKE '%' + @FilterValue + '%' OR @FilterValue = '' ) THEN 1 WHEN @FilterType = 'Match' AND @FilterColumn = 2 AND VLT.Name = @FilterValue THEN 1 WHEN @FilterType = 'NotMatch' AND @FilterColumn = 2 AND VLT.Name <> @FilterValue THEN 1 -- Tel column filter WHEN @FilterType = 'Contain' AND @FilterColumn = 3 AND ( -- In this case, when the filter value is empty, we want to show everything. VLT.Tel LIKE '%' + @FilterValue + '%' OR @FilterValue = '' ) THEN 1 WHEN @FilterType = 'NotContain' AND @FilterColumn = 3 AND ( -- In this case, when the filter value is empty, we want to show everything. VLT.Tel NOT LIKE '%' + @FilterValue + '%' OR @FilterValue = '' ) THEN 1 WHEN @FilterType = 'Match' AND @FilterColumn = 3 AND VLT.Tel = @FilterValue THEN 1 WHEN @FilterType = 'NotMatch' AND @FilterColumn = 3 AND VLT.Tel <> @FilterValue THEN 1 END ) = 1 ) SELECT Data.ID, Data.Name, Data.Tel FROM Data_CTE AS Data ORDER BY CASE WHEN @SortByField = 1 AND @SortOrder = 'ASC' THEN Data.ID END ASC, CASE WHEN @SortByField = 1 AND @SortOrder = 'DESC' THEN Data.ID END DESC, CASE WHEN @SortByField = 2 AND @SortOrder = 'ASC' THEN Data.Name END ASC, CASE WHEN @SortByField = 2 AND @SortOrder = 'DESC' THEN Data.Name END ASC, CASE WHEN @SortByField = 3 AND @SortOrder = 'ASC' THEN Data.Tel END ASC, CASE WHEN @SortByField = 3 AND @SortOrder = 'DESC' THEN Data.Tel END ASC OFFSET @PageSize * (@PageNumber - 1) ROWS FETCH NEXT @PageSize ROWS ONLY; 

对于ROW_NUMBER技术,如果您没有要使用的sorting列,则可以使用CURRENT_TIMESTAMP ,如下所示:

 SELECT TOP 20 col1, col2, col3, col4 FROM ( SELECT tbl.col1 AS col1 ,tbl.col2 AS col2 ,tbl.col3 AS col3 ,tbl.col4 AS col4 ,ROW_NUMBER() OVER ( ORDER BY CURRENT_TIMESTAMP ) AS sort_row FROM dbo.MyTable tbl ) AS query WHERE query.sort_row > 10 ORDER BY query.sort_row 

对于超过700,000的表格大小的search,这一切都非常有效。

这提取logging11到30。

您没有指定语言,也没有指定您正在使用的驱动程序。 所以我抽象地描述它。

  • 创build一个可滚动的结果集/数据集。 这需要在桌上的主要
  • 跳到最后
  • 请求行数
  • 跳转到页面的开始
  • 滚动行直到页面结束