分頁儲存過程的一點心得

2021-04-09 07:31:21 字數 2267 閱讀 7644

最近參與乙個對原有ms sqlserver2000+asp系統公升級到.net的開發專案。其中,針對某乙個資料記錄較多的表的查詢用的比較多,而且該查詢的條件組合比較複雜,包括分頁,按特定字段排序,按特定條件查詢。

參考了netkillerbasesql server 儲存過程的分頁,開始決定採用效率最高的「方案二」,即通過id標識來比較大小,從而快速檢索出所需的記錄。

方案一:

select top 頁大小 *

from testtable

where (id not in

(select top 頁大小*頁數 id

from 表

order by id))

order by id

方案二:

select top 頁大小 *

from testtable

where (id >

(select max(id)

from (select top 頁大小*頁數 id

from 表

order by id) as t))

order by id

方案三:(利用sql的游標儲存過程分頁)

create procedure xiaozhengge

@sqlstr nvarchar(4000), --查詢字串

@currentpage int, --第n頁

@pagesize int --每頁行數

as set nocount on

declare @p1 int, --p1是游標的id

@rowcount int

exec sp_cursoropen @p1 output,@sqlstr,@scrollopt=1,@ccopt=1,@rowcount=@rowcount output

select ceiling(1.0*@rowcount/@pagesize) as 總頁數--,@rowcount as 總行數,@currentpage as 當前頁

set @currentpage=(@currentpage-1)*@pagesize+1

exec sp_cursorfetch @p1,16,@currentpage,@pagesize

exec sp_cursorclose @p1

set nocount off

上文作者使用查詢分析器比較過3種方案,結論如下:

分頁方案二:(利用id大於多少和select top分頁)效率最高,需要拼接sql語句

分頁方案一:(利用not in和select top分頁) 效率次之,需要拼接sql語句

分頁方案三:(利用sql的游標儲存過程分頁) 效率最差,但是最為通用

按照「方案二」寫好查詢儲存過程後,測試中發現按照某些字段排序時,會出現記錄遺漏的情況。經過分析表中的記錄發現,原來是因為該字段內的值有重複,即用來排序的字段不能作為標識來比較大小。

找到原因後,對方案二和方案一進行了乙個整合。先使用方案二中的排序欄位的大小比較,來初步篩選符合條件的記錄,然後再使用方案一中的id標識來驗證找到記錄是否合法。最後得到的t-sql語句類似如下:

select top 頁大小 *

from testtable

where (ordercol >= select max(ordercol)

from (select top 頁大小*頁數 ordercol

from testtable

order by ordercol ))  and (id not in

(select top 頁大小*頁數 id

from testtable

order by ordercol))

order by ordercol

這種方式繼承了「方案一」的缺點,即在記錄數相當大,而且頁碼靠後時,(select top 頁大小*頁數 id

from testtable order by ordercol)所得到的記錄集會消耗相當大的記憶體。但是,於此同時,前面先進行的比較判斷(ordercol >= select max(ordercol) from (select top 頁大小*頁數 ordercol from testtable

order by ordercol ))所得到的記錄數量卻並不大,加上比較查詢的效率遠遠高於not in,所以最終的執行效率還是可以讓人接受的。

實際專案所使用的表中有1萬多條記錄,採用該分頁儲存過程查詢倒數前5頁,查詢執行時間低於1秒。而原來的asp程式使用recordset的move方法,查詢執行時間超過2秒。

SQL一點心得

sql語句將所有 stock 表裡的 縮寫 led甲 替換改寫成 led刷 update dbo stock set 縮寫 replace 縮寫 led甲 led刷 where 縮寫 like led甲 go字首 update mytable set myfield replace myfield,...

Cell myCell一點心得

ctor initializer形如 cell cell mvalue 0 mstring ctor initializer,能在建立資料成員的同時賦初值 1.const方法的工作原理是將方法內用到的資料成員都標記為const引用。因此試圖修改資料成員時,編譯器報錯。2.用explicit關鍵字標記...

openjudge 一點心得

031 校門外的樹 總時間限制 1000ms 記憶體限制 65536kb 描述某校大門外長度為l的馬路上有一排樹,每兩棵相鄰的樹之間的間隔都是1公尺。我們可以把馬路看成乙個數軸,馬路的一端在數軸0的位置,另一端在l的位置 數軸上的每個整數點,即0,1,2,l,都種有一棵樹。由於馬路上有一些區域要用來...