SQL Server 2012使用OFFSET/FETCH NEXT分页及性能测试
最近在网上看到不少文章介绍使用SQL Server 2012的新特性:OFFSET/FETCH NEXT 实现分页。多数文章都是引用或者翻译的这一篇《SQL Server 2012 - Server side paging demo using OFFSET/FETCH NEXT》,原文地址。
邀月对此也做了性能测,《SQL Server 2012服务端使用OFFSET/FETCH NEXT实现分页》,不过老外或者邀月的代码都并没有真正显示出OFFSET/FETCH NEXT的性能比起原有的ROW_NUMBER()方式好多少。
我试了下,发现主要是在取COUNT(*)上,如果OFFSET/FETCH NEXT也同时取COUNT(*),那么执行计划里一样是聚集索引Scan或者表扫描。如果不同时取COUNT(*),那么性能提升相当可观。
初始化脚本如下,生成200w条记录,用CTE递归插入,邀月的版权,^_^

USE DBAdmin
GO
/*
Setup script to create the sample table and fill it with
sample data.
*/
IF OBJECT_ID('Customers','U') IS NOT NULL
DROP TABLE Customers USE [DBAdmin]
GO CREATE TABLE [dbo].[Customers](
[CustomerID] [int] IDENTITY(1,1) NOT NULL,
[CustomerNumber] [char](8) NULL,
[CustomerName] [varchar](50) NULL,
[CustomerCity] [varchar](20) NULL,
CONSTRAINT [PK_Customers] PRIMARY KEY CLUSTERED
( [CustomerID] ASC ) ) ON [PRIMARY] GO TRUNCATE table Customers
GO DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
GO
/*****运用CTE递归插入,速度较快,邀月注***********************/
WITH Seq (num,CustomerNumber, CustomerName, CustomerCity) AS
(SELECT 1,cast('00000000'as CHAR(8)),cast('Customer 0' AS NVARCHAR(50)),cast('X-City' as NVARCHAR(20))
UNION ALL
SELECT num + 1,Cast(REPLACE(STR(num, 8), ' ', '0') AS CHAR(8)),
cast('Customer ' + STR(num,8) AS NVARCHAR(50)),
cast(CHAR(65 + (num % 26)) + '-City' AS NVARCHAR(20))
FROM Seq
WHERE num <= 2000000
)
INSERT INTO Customers (CustomerNumber, CustomerName, CustomerCity)
SELECT CustomerNumber, CustomerName, CustomerCity
FROM Seq
OPTION (MAXRECURSION 0)

2005或者2008下,使用ROW_NUMBER()分页,我把Count(*)的部分修改了:

/*
Server side paging demo using ROW_NUMBER() - SQL Server
2005/2008 version.
*/
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE SET STATISTICS IO ON;
SET STATISTICS TIME ON;
GO DECLARE @page INT, @size INT ,@Total int
SELECT @page = 700, @size = 10 select @Total = COUNT(*)
FROM Customers
WHERE CustomerCity IN ('A-City','B-City') ;WITH cte AS (
SELECT TOP (@page * @size)
CustomerID,
CustomerNumber,
CustomerName,
CustomerCity,
ROW_NUMBER() OVER(ORDER BY CustomerName ) AS Seq --,COUNT(*) OVER(PARTITION BY '') AS Total
FROM Customers
WHERE CustomerCity IN ('A-City','B-City')
ORDER BY CustomerName ASC
)
SELECT CustomerID,CustomerNumber,CustomerName,CustomerCity,@Total
FROM cte
WHERE seq BETWEEN (@page - 1 ) * @size + 1 AND @page * @size
ORDER BY seq;
GO SET STATISTICS IO OFF ;
SET STATISTICS TIME OFF;
GO

CPU及IO:

DBCC execution completed. If DBCC printed error messages, contact your system administrator.
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 47 ms. SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 0 ms.
Table 'Customers'. Scan count 5, logical reads 12600, physical reads 1, read-ahead reads 12468, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. SQL Server Execution Times:
CPU time = 483 ms, elapsed time = 1615 ms. (10 row(s) affected)
Table 'Customers'. Scan count 5, logical reads 12648, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. SQL Server Execution Times:
CPU time = 671 ms, elapsed time = 183 ms.
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms. SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 0 ms.

2012下,使用OFFSET/FETCH NEXT分页,同样,我把Count(*)的部分修改了以及ORDER BY CustomerName:

/*
Server side paging demo using the new enhancements added
in SQL Server 2012
*/
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE SET STATISTICS IO ON;
SET STATISTICS TIME ON;
GO DECLARE @page INT, @size INT,@Total int
SELECT @page = 700, @size = 10 select @Total = COUNT(*)
FROM Customers
WHERE CustomerCity IN ('A-City','B-City') SELECT
*,@Total--,COUNT(*) OVER(PARTITION BY '') AS Total
FROM Customers
WHERE CustomerCity IN ('A-City','B-City')
ORDER BY CustomerName
OFFSET (@page -1) * @size ROWS
FETCH NEXT @size ROWS ONLY;
GO SET STATISTICS IO OFF;
SET STATISTICS TIME OFF;
GO

CPU及IO:

DBCC execution completed. If DBCC printed error messages, contact your system administrator.
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 26 ms. SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 0 ms.
Table 'Customers'. Scan count 5, logical reads 12600, physical reads 1, read-ahead reads 12468, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. SQL Server Execution Times:
CPU time = 266 ms, elapsed time = 1688 ms. (10 row(s) affected)
Table 'Customers'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. SQL Server Execution Times:
CPU time = 639 ms, elapsed time = 175 ms.
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms. SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 0 ms.

可以看到IO有很大的变化,而CPU略有提升。当然也可以在CustomerCity上加上如下索引:
CREATE NONCLUSTERED INDEX IX_Customers_CustomerCity
ON [dbo].[Customers] ([CustomerCity])
INCLUDE ([CustomerNumber],[CustomerName])
加完索引后依然是OFFSET/FETCH NEXT的性能要更好。新特性使得分页的性能提升不少,.net程序员们的福音啊
SQL Server 2012使用OFFSET/FETCH NEXT分页及性能测试的更多相关文章
- SQL Server 2012使用Offset/Fetch Next实现分页
在Sql Server 2012之前,实现分页主要是使用ROW_NUMBER(),在SQL Server2012,可以使用Offset ...Rows Fetch Next ... Rows onl ...
- SQLServer · 最佳实践 · SQL Server 2012 使用OFFSET分页遇到的问题
1. 背景 最近有一个客户遇到一个奇怪的问题,以前使用ROW_NUMBER来分页结果是正确的,但是替换为SQL SERVER 2012的OFFSET...FETCH NEXT来分页出现了问题,因此,这 ...
- SQL Server 2012提供的OFFSET/FETCH NEXT与Row_Number()对比测试(转)
原文地址:http://www.cnblogs.com/downmoon/archive/2012/04/19/2456451.html 在<SQL Server 2012服务端使用OFFSET ...
- SQL Server 2012提供的OFFSET/FETCH NEXT与Row_Number()对比测试 [T]
SQL Server 2008中SQL应用系列--目录索引 前些天看到一篇文章<SQL Server 2012 - Server side paging demo using OFFSET/FE ...
- SQL Server 2012 OFFSET/FETCH NEXT分页示例(转载)
原文:http://beyondrelational.com/modules/29/presentations/483/scripts/12983/sql-server-2012-server-sid ...
- Sql Server 2012 的新分页方法分析(offset and fetch) - 转载
最近在分析 Sql Server 2012 中 offset and fetch 的新特性,发现 offset and fetch 无论语法的简洁还是功能的强大,都是相当相当不错的 其中 offset ...
- SQL Server 2012 OFFSET/FETCH NEXT分页示例
原文:http://beyondrelational.com/modules/29/presentations/483/scripts/12983/sql-server-2012-server-sid ...
- Sql Server 2012 分页方法分析(offset and fetch)
最近在分析 Sql Server 2012 中 offset and fetch 的新特性,发现 offset and fetch 无论语法的简洁还是功能的强大,都是相当相当不错的.其中 offse ...
- SQL Server 2012大幅增强T-SQL
SQL Server 2012对T-SQL进行了大幅增强,其中包括支持ANSI FIRST_VALUE和LAST_VALUE函数,支持使用FETCH与OFFSET进行声明式数据分页,以及支持.NET中 ...
随机推荐
- hdu 1400 Mondriaan's Dream 解题报告
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1400 题目意思:给出一个h * w的 大 矩形,需要用 1 * 2 的砖块去填充这个大矩形,问填充的方 ...
- java的数字精确计算问题-BigDecimal
java的数字运算,偶尔会出现精度的问题,以下阐述的 java的BigDecimal类的使用. 例如: System.out.println(0.9+0.3); 结果1.2 System.out.pr ...
- poj 3461 Oulipo(kmp统计子串出现次数)
题意:统计子串出现在主串中的次数 思路:典型kmp #include<iostream> #include<stdio.h> #include<string.h> ...
- 并不对劲的bzoj5475:loj2983:p5206:[wc2019]数树
题目大意 task0:有两棵\(n\)(n\leq10^5)个点的树\(T1,T2\),每个点的点权可以是一个在\([1,y]\)里的数,如果两个点既在\(T1\)中有直接连边,又在\(T2\)中有直 ...
- Sorting a Three-Valued Sequence
链接 分析:首先我们先对其进行排序,并看排序以后有多少个元素顺序是对的,接着我们看有多少个元素经过一次交换可以得到的,最后剩下的元素就是经过两次交换可以得到的了. /* PROB:sort3 ID:w ...
- 201响应为什么进了AJAX error回调函数
明明AJAX发送请求成功,但是后端返回的不是200,而是201,结果进了error的回调函数,想这种情况,只需要把“dataType:"json",改成dataType:" ...
- 【Cocos2dx】新建场景、场景的切换、设置启动场景与菜单的新建
这是Cocos2dx最简单的部分.主要是体现对场景的操作,其实这东西就是Flash的舞台,安卓的Activity,WIN32窗体程序的Framework窗体,网页的body,反正就是对那个容纳各种东西 ...
- bootstrap-Glyphicons 字体图标
使用的方法: 1 引入 font-awesome.css文件 2 fonts文件夹 Bootstrap 假定所有的图标字体文件全部位于 ../fonts/ 目录内(可以在font-awesome.c ...
- (bmp格式)用CDialog的OnCtlColor()消息响应处理背景画刷。
(bmp格式)用CDialog的OnCtlColor()消息响应处理背景画刷. 加载位图资源IDB_BITMAP1,在Dlg类头文件中加入: CBrush m_brush; 在OnInitDialog ...
- Codeforces - 706B - Interesting drink - 二分 - 简单dp
https://codeforces.com/problemset/problem/706/B 因为没有看见 $x_i$ 的上限是 $10^5$ ,就用了二分去做,实际上这道题因为可乐的价格上限是 $ ...