常見存儲過程分頁PK賽——簡單測試分析常見存儲過程分頁速度


數據的分頁是我們再熟悉不過的功能了,各種各樣的分頁方式層出不窮。今天我把一些常見的存儲過程分頁列出來,再簡單地測一下性能,算是對知識的總結,也是對您好想法的拋鑽引玉。廢話不多說,開始吧~~

1.首先建立一張測試表

--創建測試表
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[testTable](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [testDate] [datetime] NOT NULL CONSTRAINT [DF_testTable_testDate]  DEFAULT (getdate()),
    [name] [nvarchar](50) COLLATE Chinese_PRC_CI_AS NOT NULL,
    [description] [nchar](50) COLLATE Chinese_PRC_CI_AS NOT NULL,
    [orderColum] [float] NOT NULL,
 CONSTRAINT [PK_testTable] PRIMARY KEY CLUSTERED 
(
    [id] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

2.循環插入1000000條測試數據

declare @i int
set @i = 1
while @i < 1000001
begin
    INSERT INTO testTable([name],[description],[orderColum])
    VALUES('PageTest', 'http://www.3ymao.com', @i * rand())
    set @i = @i + 1
end

3.曬出我的系統硬件和軟件(測試環境)

好吧,准備工作完成,開始進入主題(為了方便,以下代碼我就不寫成存儲過程的方式來測試展示了)~~噔噔!首先登場的是我最常用的Not IN

1)NOT IN

declare @timediff datetime
declare @pageIndex int
declare @pageSize int
declare @sql varchar(500)
set @pageIndex=1
set @pageSize=10
set @timediff=GetDATE()
set @sql='select top ('+cast(@pageSize as varchar)+') * from testTable where (id not in (
select top '+cast(@pageSize*(@pageIndex-1) as varchar)+' id from testTable order by id)) order by id'
exec(@sql)
select datediff(ms,@timediff,Getdate())

@pageIndex=1時,運行:0ms(給力啊

@pageIndex=50000時,運行:346ms(怎么50000頁就不給力了)

@pageIndex=100000時,運行:326ms(怎么比50000頁時還少了?)

2)MAX()

declare @timediff datetime
declare @pageIndex int
declare @pageSize int
declare @sql varchar(500)
set @timediff=GetDATE()
set @pageIndex=1
set @pageSize=10
set @sql='select top ('+cast(@pageSize as varchar)+') * from testTable where (id >= (select MAX(id) from (select top '+cast((@pageSize*(@pageIndex-1)+1) as varchar)+' id from testTable order by id) as a)) order by id'
exec(@sql)
select datediff(ms,@timediff,Getdate())

@pageIndex=1時,運行:0ms(也是很給力啊

@pageIndex=50000時,運行:123ms(不錯)

@pageIndex=100000時,運行:220ms(頁數和查詢時間成正比)

3)Row_Number()

declare @timediff datetime
declare @pageIndex int
declare @pageSize int
declare @sql varchar(500)
set @timediff=GetDATE()
set @pageIndex=1
set @pageSize=10
set @sql='select * from (select *,row_number() over (order by id asc) as RowIndex from testTable) as IDWithRowNumber where RowIndex between '+cast(((@pageIndex-1)*@pageSize)+1 as varchar)+' and '+cast(@pageIndex*@pageSize as varchar)+''
exec(@sql)
select datediff(ms,@timediff,getdate())

@pageIndex=1時,運行:0ms(好吧……數據量小的時候都是這尿性)

@pageIndex=50000時,運行:280ms(略遜色)

@pageIndex=100000時,運行:580ms(這貨居然也是頁數和查詢時間成正比!坑爹吧!)

4)臨時表

declare @timediff datetime
declare @pageIndex int
declare @pageSize int
declare @sql varchar(500)
declare @str varchar(500)
set @timediff=GetDATE()
set @pageIndex=1
set @pageSize=10
set @str='with tempTable as (select ceiling((Row_number() over (order by id asc))/'+cast(@pageSize as varchar)+') as page_num,* from testTable)'
set @sql=@str+'select * from tempTable where page_num='+cast(@pageIndex-1 as varchar)+''
exec(@sql)
select datediff(ms,@timediff,getdate())

@pageIndex=1時,運行:280ms(不咧個是吧!這非主流啊)

@pageIndex=50000時,運行:280ms(這不科學……)

@pageIndex=100000時,運行:280ms(好吧,這貨不受頁數的影響,永遠都這速度)

5)中間變量

declare @timediff datetime
declare @pageIndex int
declare @pageSize int
declare @count int
declare @id int
declare @sql varchar(500)
set @pageIndex=1
set @pageSize=10
select @id=0,@count=0,@timediff=GetDATE()
select @count=@count+1,@id=case when @count=(@pageIndex-1)*@pageSize then id else @id end from testTable order by id
set @sql='select top '+cast(@pageSize as varchar)+' * from testTable where id>'+cast(@id as varchar)+''
exec(@sql)
select datediff(ms,@timediff,getdate())

@pageIndex=1時,運行:360ms(哥,不是吧,才第一頁你就這速度

@pageIndex=50000時,運行:360ms(我大概猜到100000頁時的速度了……)

@pageIndex=100000時,運行:360ms(好吧,又是不受頁數影響的貨)

 

從以上數據,我最后簡單分析總結一下:

NOT IN:數據量小的時候,速度不錯,但是數據量大的時候速度就有點遜色了,但是好在隨着查詢頁數增大,他的速度還是不會改變多少。

MAX:小數據量的時候,它的速度是最快的,但是遺憾的是查詢頁數越大,速度則越慢。

Row_Number():性質與MAX相似,但是不比MAX速度快

臨時表:不會因為查詢頁數而改變查詢速度,只和數據量大小有關,個人覺得適合大數據量而且可能會查很大的頁數時使用

中間變量:性質和臨時表相似,但是遜色於臨時表


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM