相比在SQL Server 2000 中使用的分页方式,在SQL Server 2005中使用新的语法ROW_NUMBER()来分页效率要高出很多,但是很多人在使用ROW_NUMBER()这种分页方式时,使用的方法并不正确,以下列出不正确的和正确的做法并做简单分析:

首先假设我们已经创建了如下的表和索引并初始化了100万条数据:

CREATE TABLE [dbo].[Users]
(
[ID] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) NULL,
[Test] [nchar](10) NULL,
CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED
(
[ID] ASC
) ON [PRIMARY]
) ON [PRIMARY] CREATE UNIQUE NONCLUSTERED INDEX [Inx_Name] ON [dbo].[Users]
(
[Name] ASC
) ON [PRIMARY] DECLARE @index INT
SET @index=0
WHILE @index<1000000
BEGIN
INSERT INTO [dbo].[Users]([Name],[Test]) values(@index,'walkingp')
SET @index = @index + 1
END

不正确的使用方式(查出所有数据后再排序):

SELECT ID,Name,Test
FROM (SELECT ROW_NUMBER() OVER(ORDER BY Name) AS RowNum,*
FROM dbo.Users
) AS T
WHERE RowNum BETWEEN 5000 AND 5100

正确的使用方式如下(查出主键进行排序过滤,然后使用过滤后的主键来查找数据):

SELECT A.ID,A.Name,A.Test
FROM dbo.Users AS A
INNER JOIN
(SELECT RowNum,ID
FROM (SELECT ROW_NUMBER() OVER(ORDER BY Name) AS RowNum,ID
FROM dbo.Users) AS T
WHERE RowNum BETWEEN 4000 AND 4100) as B
ON A.ID = B.ID
ORDER BY B.RowNum

以下具体分析:

SET STATISTICS IO ON
SET STATISTICS TIME ON
GO PRINT 'Error.5000-------------------------'
DECLARE @time DATETIME
DECLARE @ms INT
SET @time= GETDATE() SELECT ID,Name,Test
FROM (SELECT ROW_NUMBER() OVER(ORDER BY Name) AS RowNum,*
FROM dbo.Users) AS T
WHERE RowNum BETWEEN 5000 AND 5100 SET @ms=DATEDIFF(ms,@time,GETDATE())
PRINT @ms--毫秒数
GO PRINT 'Right.5000-------------------------'
DECLARE @time DATETIME
DECLARE @ms INT
SET @time= GETDATE() SELECT A.ID,A.Name,A.Test
FROM dbo.Users AS A
INNER JOIN
(SELECT RowNum,ID
FROM (SELECT ROW_NUMBER() OVER(ORDER BY Name) AS RowNum,ID
FROM dbo.Users) AS T
WHERE RowNum BETWEEN 5000 AND 5100) AS B
ON A.ID = B.ID
ORDER BY B.RowNum SET @ms=DATEDIFF(ms,@time,GETDATE())
PRINT @ms--毫秒数
GO PRINT 'Error.500000-------------------------'
DECLARE @time DATETIME
DECLARE @ms INT
SET @time= GETDATE() SELECT ID,Name,Test
FROM (SELECT ROW_NUMBER() OVER(ORDER BY Name) AS RowNum,*
FROM dbo.Users) AS T
WHERE RowNum BETWEEN 500000 AND 500100 SET @ms=DATEDIFF(ms,@time,GETDATE())
PRINT @ms--毫秒数
GO PRINT 'Right.500000-------------------------'
DECLARE @time DATETIME
DECLARE @ms INT
SET @time= GETDATE() SELECT A.ID,A.Name,A.Test
FROM dbo.Users AS A
INNER JOIN
(SELECT RowNum,ID
FROM (SELECT ROW_NUMBER() OVER(ORDER BY Name) AS RowNum,ID
FROM dbo.Users) AS T
WHERE RowNum BETWEEN 500000 AND 500100) AS B
ON A.ID = B.ID
ORDER BY B.RowNum SET @ms=DATEDIFF(ms,@time,GETDATE())
PRINT @ms--毫秒数
GO PRINT 'Error.900000-------------------------'
DECLARE @time DATETIME
DECLARE @ms INT
SET @time= GETDATE() SELECT ID,Name,Test
FROM (SELECT ROW_NUMBER() OVER(ORDER BY Name) AS RowNum,*
FROM dbo.Users) AS T
WHERE RowNum BETWEEN 900000 AND 900100 SET @ms=DATEDIFF(ms,@time,GETDATE())
PRINT @ms--毫秒数
GO PRINT 'Right.900000-------------------------'
DECLARE @time DATETIME
DECLARE @ms INT
SET @time= GETDATE() SELECT A.ID,A.Name,A.Test
FROM dbo.Users AS A
INNER JOIN
(SELECT RowNum,ID
FROM (SELECT ROW_NUMBER() OVER(ORDER BY Name) AS RowNum,ID
FROM dbo.Users) AS T
WHERE RowNum BETWEEN 900000 AND 900100) AS B
ON A.ID = B.ID
ORDER BY B.RowNum SET @ms=DATEDIFF(ms,@time,GETDATE())
PRINT @ms--毫秒数

以下是SQL的统计信息:

Error.5000-------------------------

(101 row(s) affected)
Table 'Users'. Scan count 1, logical reads 15649, 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 = 31 ms,  elapsed time = 35 ms.

36

Right.5000-------------------------

(101 row(s) affected)
Table 'Users'. Scan count 1, logical reads 325, 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 = 0 ms,  elapsed time = 7 ms.

6

Error.500000-------------------------

(101 row(s) affected)
Table 'Users'. Scan count 1, logical reads 1532807, 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 = 1797 ms,  elapsed time = 1789 ms.

1786

Right.500000-------------------------

(101 row(s) affected)
Table 'Users'. Scan count 1, logical reads 1545, 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 = 453 ms,  elapsed time = 454 ms.

453

Error.900000-------------------------

(101 row(s) affected)
Table 'Users'. Scan count 1, logical reads 2758790, 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 = 3266 ms,  elapsed time = 3280 ms.

3273

Right.900000-------------------------

(101 row(s) affected)
Table 'Users'. Scan count 1, logical reads 2528, 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 = 750 ms,  elapsed time = 748 ms.

750

  通过分析可以看出错误的使用方式逻辑读要比正确的使用方式的逻辑读大的多,而且页码越大读的越多,最终导致效率越来越差,这点也可以通过执行计划看出端倪。

希望对您有所帮助^_^。

使用SQL Server 2005 新的语法ROW_NUMBER()进行分页的两种不同方式的性能比较的更多相关文章

  1. 转载--SQL Server 2005的XQuery介绍

    原文地址: http://bbs.51cto.com/thread-458009-1-1.html   引用: 摘要 本文介绍了SQL Server 2005能够支持的XQuery的各方面特性如FLW ...

  2. python常有模块:模块、引入语法、两种执行方式、模块搜索顺序

    今天主要讲了以下几点:一.模块三问.定义及分类二.import和from的语法三.文件的两种执行方式及搜索顺序四.内置函数 一.模块.import和from的语法 1.什么是模块   模块是一堆功能函 ...

  3. sql server 2000 对应 sql server 2005的row_number()、rank()、DENSE_RANK( )、ntile( )等用法

    转自CSDN:http://blog.csdn.net/htl258/article/details/4006717 SQL server 2005新增的几个函数,分别是row_number( ).r ...

  4. SQL Server 2005的几个新功能

    SQL Server 2005相对于SQL Server 2000改进很大,有些还是非常实用的. 举几个例子来简单说明 这些例子我引用了Northwind库. 1. TOP 表达式  SQL Serv ...

  5. SQL SERVER 2005快捷键+visual studio 2008 快捷键

    一.SQL SERVER 2005快捷键  快捷键                                       功能           CTRL       +       SHIF ...

  6. 浅析SQL Server 2005中的主动式通知机制

    一.引言 在开发多人同时访问的Web应用程序(其实不只这类程序)时,开发人员往往会在缓存策略的设计上狠下功夫.这是因为,如果将这种环境下不常变更的数据临时存放在应用程序服务器或是用户机器上的话,可以避 ...

  7. SQL Server 2005的XML数据修改语言(XML DML)

    转:http://www.microsoft.com/china/msdn/library/data/sqlserver/XMLDML.mspx?mfr=true 作为对XQuery语言的扩展,XML ...

  8. SQL server 2005 PIVOT运算符的使用

    原文:SQL server 2005 PIVOT运算符的使用 PIVOT,UNPIVOT运算符是SQL server 2005支持的新功能之一,主要用来实现行到列的转换.本文主要介绍PIVOT运算符的 ...

  9. 【转】SQL SERVER 2005中如何获取日期(一个月的最后一日、上个月第一天、最后一天、一年的第一日等等)

    在网上找到的一篇文章,相当不错哦O(∩_∩)O~ //C#本周第一天            int dayOfWeek = Convert.ToInt32(DateTime.Now.DayOfWeek ...

随机推荐

  1. openstack系列阅读目录

    一 keystone系列 keystone基础 网关协议cgi,fastcgi,wsgi,uwsgi keystone源码分析 keystone部署及使用 keystone客户端工作介绍 二 glan ...

  2. [BZOJ]2132: 圈地计划 最小割

    圈地计划 Description 最近房地产商GDOI(Group of Dumbbells Or Idiots)从NOI(Nuts Old Idiots)手中得到了一块开发土地.据了解,这块土地是一 ...

  3. POJ 3130 How I Mathematician Wonder What You Are! /POJ 3335 Rotating Scoreboard 初涉半平面交

    题意:逆时针给出N个点,求这个多边形是否有核. 思路:半平面交求多边形是否有核.模板题. 定义: 多边形核:多边形的核可以只是一个点,一条直线,但大多数情况下是一个区域(如果是一个区域则必为 ).核内 ...

  4. SQL Server 127个SQL server热门资料汇总

      SQL Server 127个SQL server热门资料汇总     最近有许多关于如何学习SQLSERVER的问题,其实新手入门的资源和贴子很多,现在向大家隆重推荐经过精心整理的[SQLSer ...

  5. cocos2d-x ScrollView、TableView

    转自:http://codingnow.cn/cocos2d-x/1024.html 在游戏和应用中经常要实现左右滑动展示游戏帮助.以列表显示内容的UI效果,就像android中的Gallery和Li ...

  6. iOS 根据文件名获取到文件路径

    根据文件名来获取文件路径(Document目录下) //根据文件名来获取文件路径 - (NSString *)dataFilePath:(NSString *)sender { NSArray *pa ...

  7. 实战:ORACLE SQL Performance Analyzer

    通过 SPA,您能够依据各种更改类型(如初始化參数更改.优化器统计刷新和数据库升级)播放特定的 SQL 或整个 SQL 负载,然后生成比較报告,帮助您评估它们的影响. 在 Oracle Databas ...

  8. 从零开始学android开发-IDE空间不够报错

    E:\ProSoft\adt-bundle-windows-x86-20140321\eclipse目录下 右键eclipse用记事本打开 可以设置运行的最大的运行空间

  9. Android Intent入门

    http://www.cnblogs.com/leipei2352/archive/2011/08/09/2132096.html http://blog.csdn.net/xiazdong/arti ...

  10. android学习日记02--Activity简介

    一.Activity活动 学习Android,第一个都会接触Activity滴,Activity表示一个用户界面,是Android应用程序的入口,可以同时有多个界面,但只会显示栈顶的界面. Activ ...