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中 ...
随机推荐
- poj 3461 Oulipo(kmp统计子串出现次数)
题意:统计子串出现在主串中的次数 思路:典型kmp #include<iostream> #include<stdio.h> #include<string.h> ...
- maven实战(4)-- maven构建自己的jar到本地仓库中
在平时的开发中,经常需要用到自己以前开发的一个jar包,那么如何使用将自己开发的jar提交到本地仓库中,供其他的项目依赖呢?主要有三种方法: (1)使用mvn的构建命令:mvn clean insta ...
- [Selenium] 使用Chrome Driver 的示例
//导入Selenium 库和 ChromeDriver 库 pachage com.learningselenium.simplewebdriver; import java.util.concur ...
- 【BZOJ 3884】 上帝与集合的正确用法
[题目链接] 点击打开链接 [算法] 通过欧拉拓展定理,列出递推公式 [代码] #include<bits/stdc++.h> using namespace std; typedef l ...
- 【转】git修改文件后,提交到远程仓库
原文地址:https://blog.csdn.net/nly19900820/article/details/73613654 修改文件后,怎么提交到远程仓库1.git status 查看git是否有 ...
- 用js实现的一个可拖动标签的例子
先贴代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w ...
- Gulp安装及配合组件构建前端开发一体化(转)
Gulp安装及配合组件构建前端开发一体化 所有功能前提需要安装nodejs(本人安装版本v0.10.26)和ruby(本人安装版本1.9.3p484). Gulp 是一款基于任务的设计模式的自动化工具 ...
- spring+mybatis下delete和insert返回值-2147482646
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate"&g ...
- SCUT - 48 - 飞行员的配对方案 - 费用流
https://scut.online/p/48 一道二分图匹配,跑费用流就可以过了(其实最大流都可以了). #include<bits/stdc++.h> #define MAXN_ 5 ...
- Android6.0 危险权限和普通权限
Normal Permissions如下 ACCESS_LOCATION_EXTRA_COMMANDS ACCESS_NETWORK_STATE ACCESS_NOTIFICATION_POLICY ...