Sql Server2005的一个新特性便是我等了很久的Row_Number(),以前用Oracle时用rownumber写分页存储过程很方便:)
下面是我做的一个小小的测试,测试我原来在sql server2000下所用的分页存储过程与使用Row_Number()编写的存储过程在Sql Server2005上的执行效率
数据表:
REATE TABLE [dbo].[test](
[UserId] [int] Primary Key IDENTITY(1,1) ,
[UserName] [nvarchar](256) ,
[Sex] [varchar](50) NOT NULL,
[Age] [int] NOT NULL,
[Address] [varchar](100) ,
[status] [bit] NULL,
[Email] [varchar](100) ,
[InsertDate] [datetime] NOT NULL
)
插入1000k记录
use temp
Go
declare @n int
set @n = 0
while @n<1000000
BEGIN
Insert Into test(UserName,Sex,Age,Address,status,Email,InsertDate)
Values(''bbisky'',''男'',''25'',''中国传媒大学现代远程教育中心'',1,''denghaibo@live.com'',getdate())
Select @n = @n+1
END
两个存储过程
原来使用Top的分页存储过程
Create proc [dbo].[test_PageById]
(
@pageIndex int,
@pageSize int
)
AS
SELECT TOP(@pageSize) *
FROM test
WHERE UserId <
(SELECT MIN(UserId) FROM (
SELECT TOP ((@pageIndex-1) * @pageSize) UserId
FROM test
ORDER BY UserId DESC)B )
ORDER BY UserId DESC
使用Row_number的存储过程
CREATE proc [dbo].[test_PageByRowNumber]
(
@pageIndex int,
@pageSize int
)
AS
DECLARE @startRow int, @endRow int
Set @startRow = (@pageIndex - 1) * @pageSize +1
SET @endRow = @startRow + @pageSize -1
SELECT*
FROM (
SELECT *,ROW_NUMBER() OVER (ORDER BY UserId DESC) AS RowNumber
FROM test ) T
WHERE T.RowNumber BETWEEN @startRow AND @endRow
测试和结果
SET STATISTICS io ON
SET STATISTICS time ON
go
EXEC test_PageByRowNumber 1000,50 --RowNumber存储过程
go
SET STATISTICS profile OFF
SET STATISTICS io OFF
SET STATISTICS time OFF
/*结果分析*/
SQL Server 分析和编译时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
SQL Server 分析和编译时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
(50 行受影响)
表 ''test''。扫描计数 1,逻辑读取 50098 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
SQL Server 执行时间:
CPU 时间 = 219 毫秒,占用时间 = 213 毫秒。
SQL Server 执行时间:
CPU 时间 = 219 毫秒,占用时间 = 213 毫秒。
SQL Server 分析和编译时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
SET STATISTICS io ON
SET STATISTICS time ON
go
EXEC test_PageById 1000,50 --执行使用top语句的存储过程
go
SET STATISTICS profile OFF
SET STATISTICS io OFF
SET STATISTICS time OFF
/*结果分析*/
SQL Server 分析和编译时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
SQL Server 分析和编译时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
(50 行受影响)
表 ''test''。扫描计数 2,逻辑读取 153 次,物理读取 0 次,预读 93 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
SQL Server 执行时间:
CPU 时间 = 16 毫秒,占用时间 = 26 毫秒。
SQL Server 执行时间:
CPU 时间 = 16 毫秒,占用时间 = 26 毫秒。
SQL Server 分析和编译时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。至此可以很直观的看出差距了.使用原来的Top子句的存储过程比使用Row_Number()的存储过程执行时间快了将近10倍..
其实直接分析语句也可以看出,Row_Number()的效率不会是最高的,因为它必须先为100万条记条生成RowNumber,自然不会快到哪里去了.
不过前者的适应范围有些限制,即必须有一个为数字的唯一字段,如果使用uniqueidentifier为主键的话则不能使用了.
Row_Number分页有很好的通用性和直观易用性,对于数据量较少来说,二者应该不会有很大的区别,使用哪个就看你自己的需要了.