數據庫分頁查詢

服務器端幾種分頁方式的性能分析

   ——by comaple 2011-6-17

前言:

本試驗在於探討分頁的性能問題,當然客戶端分頁也是一種分頁的策略。不過這種分頁方式已經過時了,建議不要採用。這裏我們只討論服務器端分頁。

實驗環境:

PentiumR) dual-Core CPU E5300 @ 2.6GHz 2.59GHz, 2.00GB內存

SqlServer2008 數據庫環境,數據庫中我們要用到的的表: 

dbo.GMpipe

CREATE TABLE [dbo].[GMpipe](

[GMDataID] [uniqueidentifier] NOT NULL,

[pointID] [uniqueidentifier] NULL,

[measurePipe] [varchar](10) NULL,

[measureTime] [datetime] NULL,

[measureCycle] [varchar](10) NULL,

[MeasureData] [int] NULL,

[doseRateValue] [decimal](18, 10) NULL,

 CONSTRAINT [PK_GMPIPE] PRIMARY KEY CLUSTERED 

(

[GMDataID] ASC

)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]

) ON [PRIMARY]

目前該表中存在1157226條數據,用select語句查詢耗時爲:17s

SELECT  * FROM dbo.GMpipe ORDER BY measureTime DESC

接下來我們就來一起體驗一下把:

第一種方式

使用top語句(本文只列出常用的):

分頁的存儲過程,已實現好了如下:

CREATE PROCEDURE paging1

 @pageNum INT -頁碼

 ,@Num INT    --每頁條數

AS

BEGIN

SELECT TOP (@Num) *  FROM 

(

SELECT TOP (@Num*@pageNum) * FROM dbo.GMpipe ORDER BY dbo.GMpipe.measureTime asc

) b ORDER BY b.measureTime DESC;

END

go

這個中方法先把數據庫中的前@Num*@pageNum條數據取出,再從結果集中取出最後的@Num條數據,當然兩個排序規則是不一樣的這點很重要,不然起不到分頁效果。 你可以具體試一下就明白了。

看性能

EXEC paging1 2,5;--每頁五條,第十頁數據 耗時:1s

EXEC paging1 200,5;--每頁五條,第200頁數據 耗時:1s

EXEC paging1 20000,5;--每頁五條,第20000頁數據 耗時:1s

EXEC paging1 200000,5;--每頁五條,第二十萬頁數據 耗時: 3s

第二中方式

使用臨時表

分頁的存儲過程,實現如下:

CREATE PROCEDURE paging2

 @pageNum INT

,@Num INT

AS

BEGIN

SELECT  measurePipe,measureTime,measureCycle,MeasureData,doseRateValue,IDENTITY(int) Num INTO #temp FROM dbo.GMpipe ORDER BY measureTime ASC 

SELECT * FROM #temp WHERE  Num<=@Num*@pageNum AND Num> @Num*(@pageNum-1)

ORDER BY Num ASC

DROP TABLE #temp

END

Go

這種方式是將表中的數據全部查出,然後加入標識行號的列Num並將其裝入臨時表#temp中然後可根據行號列進行分頁查詢。

看性能

EXEC paging2 2,5;--每頁五條,第二頁數據 耗時:3s

EXEC paging2 200,5;--每頁五條,第二頁數據 耗時:3s

EXEC paging2 20000,5;--每頁五條,第二頁數據 耗時:3s

EXEC paging2 200000,5;--每頁五條,第二十萬頁數據 耗時:3s

第三種方式

採用系統提供的ROW_NUMBER()函數

存儲過程實現如下:

CREATE PROCEDURE paging0  

 @pageNum INT

 ,@Num INT

 AS 

 begin

SELECT * FROM 

(

SELECT measurePipe,measureTime,measureCycle,MeasureData,doseRateValue,ROW_NUMBER() OVER(ORDER BY  GMpipe.measureTime ASC ) AS NUM 

FROM GMpipe)A

WHERE A.NUM<=@Num*@pageNum AND A.NUM> @Num*(@pageNum-1) ORDER BY A.measureTime desc

END

Go

這種方式就不多說了大家一看就明白,直接看性能。

看性能

EXEC paging0 20,5;--每頁五條,第二十頁數據 耗時: 1s

EXEC paging0 20000,5;--每頁五條,第二頁數據 耗時: 1s

EXEC paging0 200000,5;--每頁五條,第二十萬頁數據 耗時: 1s
改進第三種方式:

 之所以要改進第三種方式那是因爲,Top關鍵字其實是

已經經過性能優化了的之所以比不過ROW_NUMBER()的執行效率是因爲用了兩次,那麼既然如此,我們何不將二者結合起來使用,效果豈不更佳。那就讓我們改進一下吧。

 

CREATE PROCEDURE paging0

@pageNum INT

,@Num INT

AS

begin

SELECT * FROM

(

SELECT TOP (@Num*@pageNum)  measurePipe,measureTime,measureCycle,MeasureData,

          doseRateValue,ROW_NUMBER() OVER(ORDER BY GMpipe.measureTime ASC ) AS NUM

FROM GMpipe)A

WHERE A.NUM> @Num*(@pageNum-1) ORDER BY A.measureTime desc

END

Go

 這樣一來執行效率更高了呵呵!

 

總結

我們再來改變一下每頁的條數看看

臨時表方式:

EXEC paging2 5000,200;--每頁兩百條,第五千頁數據 耗時:7s

Top語句方式:

EXEC paging1 5000,200;-- 每頁兩百條,第五千頁數據 耗時: 3s

ROW_NUMBER()函數方式:

EXEC paging0 5000,200;--每頁五條,第二十萬頁數據 耗時:1s

分析:這樣我們就能看到很清楚了吧,影響top語句方式的因素是你要取的頁數,即越靠後耗時也明顯。影響臨時表的因素則比較多了首先是數據的總條數,其次是分頁方式即每頁的數據量。而ROW_NUMBER()函數的影響則可能只有總的數據量,並且性能可是不錯的哦!

我想對與一般的系統而言二十萬頁的數據分頁量已經夠用了吧,呵呵!再多的話我們也看不過來啊

發佈了40 篇原創文章 · 獲贊 59 · 訪問量 25萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章