程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> Oracle數據庫 >> Oracle教程 >> 使用rowid抽取數據方法以及大數據量游標卡住的應對,rowid游標

使用rowid抽取數據方法以及大數據量游標卡住的應對,rowid游標

編輯:Oracle教程

使用rowid抽取數據方法以及大數據量游標卡住的應對,rowid游標


平時工作的時候,經常會遇到這種事情,從一個大表A中,抽取字段a在一個相對較小B的表的數據,比如,從一個詳單表中,抽取幾萬個用戶號碼的話單出來。這種時候,一般來說,

做關聯查詢:

create table A1 as select A.* from 詳單表 A,號碼表 B wherea.號碼 = b.號碼

當然這個語句根據情況不一樣有很多中寫法,但是,不管是哪種寫法,這個語句最大的問題是,如果數據量大,你非常糾結他到底能不能跑完,有時候一個事情,要求2個小時干完,現在跑了1個小時,你說到底要不要結束它另外想辦法呢?

 

所以,這種時候,還是讓事情可控一點比較好,首先,還是要考慮a字段的特征,如果a字段並集很大,A有上億,a字段有幾百萬,這種時候,我們會給a字段建上索引,比如我要抽取1萬個號碼的詳單,這樣寫其實就很好:

for x in (select 號碼 from Bwhere B.狀態="未處理") loop

insert into A1 select * from A where a.號碼=x.號碼 ;

update B set B.狀態=已處理 where B.號碼=x.號碼 ;

commit ;

end loop;

這樣的好處,第一你可以看到執行了多少,進度可控,第二,你隨時可以停了他繼續。下次啟動時,前面做完的他就不會繼續做了。

 

但是,當a字段的並集,不是那麼大,而是比較小的時候,比如只有十萬的時候, 就不怎麼舒服了,因為這種時候索引就沒那麼管用了。當然你還是可以按照上面的方式那樣去做,只是會很慢很慢。所以,這個時候考慮完全做一次全表掃描,實際比索引字段查詢多次還要快(為了貼近實際,我把這個字段叫做文件名跟上面的號碼區分):

 

for x in (select rowid,文件名 from A)

select count(1) into cc from B where B.文件名=x.文件名 ;

if cc >= 1 then

insert into A1 select * from A where A.rowid=x.rowid;

commit ;

end if ;

end loop;

上面語句中,其實這麼寫是偷懶的做法,因為要插一條記錄去新表A1中,理想的辦法當然是在游標中讀取所有字段,然後直接insert 到A1中,用insert into A1 values這種,如果寫成insert into A1 select * from A where A.rowid=x. rowid會增加IO,實際上,rowid定位一行數據是極快的方法(不管你表有多大,都是一樣的效率),這種寫法根本不會比insert into A1 values 慢多少。

 

再次但是,這種場景下,其實是容易出問題,問題出在這個數據量很大,且記錄不怎麼連續的時候,當記錄不怎麼連續時,游標fentch到越後面,就越慢。一個億的記錄,沒准在幾百萬的時候就卡住了。出現問題的原因,還是因為記錄不夠連續,導致尋址變慢,解決的辦法,就是重建這個表(或者對這個表做表分析)。

 

再次再次但是,上億的表,做表分析也好,還是重建,都不容易,可能重建個幾個小時還是建不出來,而且浪費空間。所以,上面那個是想偷懶少些字段的邏輯,就變成了必然,我們考慮重建表的時候,只需要兩個字段:

create table A1的映射 nolloggingas select rowid as rrowid , 文件名 from A ;

for x in (select rrowid,文件名 from A1的映射)

select count(1) into cc from B where B.文件名=x.文件名 ;

if cc >= 1 then

insert into A1 select * from A where A.rowid=x.rrowid;

commit ;

end if ;

end loop;

重建表的時候,只用兩個字段,可以大大減少重建的時間(create table 其實是獲取的數據量越大越慢,還不是線性的,是幾何增長的)。然後游標使用新的重建表,讀取rowid字段(已經改為了rrowid),在根據獲取到的rowid去實際表中獲取數據。

 

要不怎麼說,這個世界是懶人推動的呢?

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved