提取海量資料的通用SQL儲存過程

2021-04-18 04:09:14 字數 3506 閱讀 2115

在大資料量的情況下,特別是在查詢最後幾頁的時候,查詢時間一般不會超過9秒;而用其他儲存過程,在實踐中就會導致超時,所以這個儲存過程非常適用於大容量資料庫的查詢。

create procedure sp_pager

@tblname varchar(255),       -- 表名

@strgetfields varchar(1000) = '*',  -- 需要返回的列

@fldname varchar(255)='',      -- 排序的欄位名

@pagesize int = 10,          -- 頁尺寸

@pageindex int = 1,           -- 頁碼

@docount bit = 0,   -- 只返回記錄總數, 非 0 值則返回

@ordertype bit = 0,  -- 設定排序型別, 非 0 值則降序

@strwhere varchar(1500) = ''  -- 查詢條件 (注意: 不要加 where)

asdeclare @strsql varchar(5000)       -- 主語句

declare @strtmp varchar(110)        -- 臨時變數

declare @strorder varchar(400)        -- 排序型別

if @docount != 0

begin

if @strwhere !=''

set @strsql = "select count(*) as total from [" + @tblname + "] where "+@strwhere

else

set @strsql = "select count(*) as total from [" + @tblname + "]"

end 

--以上**的意思是如果@docount傳遞過來的不是0,就執行總數統計。以下的所有**都是@docount為0的情況

else

begin

if @ordertype != 0

begin

set @strtmp = "<(select min"

set @strorder = " order by [" + @fldname +"] desc"

--如果@ordertype不是0,就執行降序,這句很重要!

endelse

begin

set @strtmp = ">(select max"

set @strorder = " order by [" + @fldname +"] asc"

endif @pageindex = 1

begin

if @strwhere != ''  

set @strsql = "select top " + str(@pagesize) +" "+@strgetfields+ "  from [" + @tblname + "] where " + @strwhere + " " + @strorder

else

set @strsql = "select top " + str(@pagesize) +" "+@strgetfields+ "  from ["+ @tblname + "] "+ @strorder

--如果是第一頁就執行以上**,這樣會加快執行速度

endelse

begin

--以下**賦予了@strsql以真正執行的sql**

set @strsql = "select top " + str(@pagesize) +" "+@strgetfields+ "  from ["

+ @tblname + "] where [" + @fldname + "]" + @strtmp + "(["+ @fldname + "]) from (select top " + str((@pageindex-1)*@pagesize) + " ["+ @fldname + "] from [" + @tblname + "]" + @strorder + ") as tbltmp)"+ @strorder

if @strwhere != ''

set @strsql = "select top " + str(@pagesize) +" "+@strgetfields+ "  from ["

+ @tblname + "] where [" + @fldname + "]" + @strtmp + "(["

+ @fldname + "]) from (select top " + str((@pageindex-1)*@pagesize) + " ["

+ @fldname + "] from [" + @tblname + "] where " + @strwhere + " "

+ @strorder + ") as tbltmp) and " + @strwhere + " " + @strorder

end

end  

exec (@strsql)

go下面談一談聚集索引的重要性和如何選擇聚集索引

雖然在超大容量情況下,上面的分頁儲存過程分頁的實現過程是很快的,但在分前幾頁時,這個1-3秒的速度甚至比沒有經過優化的分頁方法速度還要慢,借使用者的話說就是「還沒有access資料庫速度快」,這個認識足以導致使用者放棄使用您開發的系統。

分析一下,原來產生這種現象的癥結是如此的簡單,但又如此的重要:排序的字段不是聚集索引!

聚集索引有兩個最大的優勢:

1、以最快的速度縮小查詢範圍。

2、以最快的速度進行字段排序。

第1條多用在查詢優化時,而第2條多用在進行分頁時的資料排序。

而聚集索引在每個表內又只能建立乙個,這使得聚集索引顯得更加的重要。聚集索引的挑選可以說是實現「查詢優化」和「高效分頁」的最關鍵因素。

但要既使聚集索引列既符合查詢列的需要,又符合排序列的需要,這通常是乙個矛盾。

在表裡新建乙個日期列作為聚集索引的起始列,日期的精確度為「日」。這種作法的優點是,在進行劃時間段的快速查詢中,比用id主鍵列有很大的優勢。

但在分頁時,由於這個聚集索引列存在著重覆記錄,所以無法使用max或min來最為分頁的參照物,進而無法實現更為高效的排序。而如果將id主鍵列作為聚集索引,那麼聚集索引除了用以排序之外,沒有任何用處,實際上是浪費了聚集索引這個寶貴的資源。

為解決這個矛盾,所以新增了乙個日期列,其預設值為getdate()。使用者在寫入記錄時,這個列自動寫入當時的時間,時間精確到毫秒。即使這樣,為了避免可能性很小的重合,還要在此列上建立unique約束。將此日期列作為聚集索引列。

有了這個時間型聚集索引列之後,使用者就既可以用這個列查詢使用者在插入資料時的某個時間段的查詢,又可以作為唯一列來實現max或min,成為分頁演算法的參照物。

經過這樣的優化發現,無論是大資料量的情況下還是小資料量的情況下,分頁速度一般都是幾十毫秒,甚至0毫秒。而用日期段縮小範圍的查詢速度比原來也沒有任何遲鈍。

聚集索引是如此的重要和珍貴,所以,一定要將聚集索引建立在:

1、您最頻繁使用的、用以縮小查詢範圍的字段上;

2、您最頻繁使用的、需要排序的字段上。

mysql 通用儲存過程分頁 海量資料分頁

老話題了,不多說了看 吧 測試表create table if not exists test id int 11 not null auto increment,sort int 11 title varchar 50 primary key id engine innodb default ch...

mysql 通用儲存過程分頁 海量資料分頁

測試表 create table if not exists test id int 11 not null auto increment,sort int 11 title varchar 50 primary key id engine innodb default charset gb2312...

通用的SQL資料分頁儲存過程

create procedure spgetpageofrecords pagesize int 20,分頁大小 currentpage int 第幾頁 columns varchar 1000 需要得到的字段 tablename varchar 100 需要查詢的表 condition varch...