使用SQL Server 2005 新的语法ROW_NUMBER()进行分页的两种不同方式的性能比较
相比在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()进行分页的两种不同方式的性能比较的更多相关文章
- 转载--SQL Server 2005的XQuery介绍
原文地址: http://bbs.51cto.com/thread-458009-1-1.html 引用: 摘要 本文介绍了SQL Server 2005能够支持的XQuery的各方面特性如FLW ...
- python常有模块:模块、引入语法、两种执行方式、模块搜索顺序
今天主要讲了以下几点:一.模块三问.定义及分类二.import和from的语法三.文件的两种执行方式及搜索顺序四.内置函数 一.模块.import和from的语法 1.什么是模块 模块是一堆功能函 ...
- 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 ...
- SQL Server 2005的几个新功能
SQL Server 2005相对于SQL Server 2000改进很大,有些还是非常实用的. 举几个例子来简单说明 这些例子我引用了Northwind库. 1. TOP 表达式 SQL Serv ...
- SQL SERVER 2005快捷键+visual studio 2008 快捷键
一.SQL SERVER 2005快捷键 快捷键 功能 CTRL + SHIF ...
- 浅析SQL Server 2005中的主动式通知机制
一.引言 在开发多人同时访问的Web应用程序(其实不只这类程序)时,开发人员往往会在缓存策略的设计上狠下功夫.这是因为,如果将这种环境下不常变更的数据临时存放在应用程序服务器或是用户机器上的话,可以避 ...
- SQL Server 2005的XML数据修改语言(XML DML)
转:http://www.microsoft.com/china/msdn/library/data/sqlserver/XMLDML.mspx?mfr=true 作为对XQuery语言的扩展,XML ...
- SQL server 2005 PIVOT运算符的使用
原文:SQL server 2005 PIVOT运算符的使用 PIVOT,UNPIVOT运算符是SQL server 2005支持的新功能之一,主要用来实现行到列的转换.本文主要介绍PIVOT运算符的 ...
- 【转】SQL SERVER 2005中如何获取日期(一个月的最后一日、上个月第一天、最后一天、一年的第一日等等)
在网上找到的一篇文章,相当不错哦O(∩_∩)O~ //C#本周第一天 int dayOfWeek = Convert.ToInt32(DateTime.Now.DayOfWeek ...
随机推荐
- 如何计算ModBus超时时间?
波特率:每秒钟通过信道传输的信息量称为位传输速率,也就是每秒钟传送的二进制位数,简称比特率.比特率表示有效数据的传输速率,用b/s .bit/s.比特/秒,读作:比特每秒. 如9600b/s:指总线上 ...
- 编写Qt Designer自定义控件(二)——编写自定义控件界面
接上文:编写Qt Designer自定义控件(一)——如何创建并使用Qt自定义控件 既然是控件,就应该有界面,默认生成的控件类只是一个继承了QWidget的类,如下: #ifndef LOGLATED ...
- JBOss 端口没占用!
打开exlipse ,启动服务器 后,报如下错误:
- 【Stage3D学习笔记续】真正的3D世界(二):显示模型
虽然我们进入真3D世界了,但是上一章的Demo仍然是显示的一个平面,尽管我们的平面在3D空间中旋转可以看出一点3D透视的效果,但是既然是真3D,就要拿出点3D的样子来! 如果要显示3D模型,我们就要告 ...
- centos 卸载自带的 java
一般情况下,我们都要将linux自带的OPENJDK卸载掉,然后安装SUN的JDK 首先:查看Linux自带的JDK是否已安装 <1># java -version ...
- Using breakpad in cocos2d-x 3.2,dump信息收集
作者:HU 转载请注明,原文链接:http://www.cnblogs.com/xioapingguo/p/4037268.html 一.基本步骤 1.生成转换工具 2.把breakpad加入到项目 ...
- iOS UICollectionView基础
转载自:http://www.cnblogs.com/wayne23/p/4013522.html 初始化部分: UICollectionViewFlowLayout *flowLayout= [[ ...
- 【转】placement new
原文:http://www.cnblogs.com/wanghetao/archive/2011/11/21/2257403.html 1. placement new的含义placement new ...
- ThinkPHP CURD方法盘点:data方法
data方法也是模型类的连贯操作方法之一,用于设置当前要操作的数据对象的值,可能大家不太习惯用这个方法,今天来讲解下如何用好data方法. 用法 写操作 通常情况下我们都是通过create方法或者赋值 ...
- 一个仿 github for windows 及 windows 8 的进度条
https://github.com/wly2014/ProgressBar