日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
Oracle構(gòu)造序列的方法分析對比

關(guān)于Oracle的序列,相信大家并不陌生,但很多人平時只用到connect by 的方式來構(gòu)造序列,今天一起來學習更多的構(gòu)造序列的方法及每個方法的優(yōu)缺點。

創(chuàng)新互聯(lián)公司堅持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:網(wǎng)站制作、成都網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時代的湯陰網(wǎng)站設(shè)計、移動媒體設(shè)計的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

Oracle構(gòu)造序列的方法隨著版本一直在變化。在9i之前的版本,常用的方法是:

 
 
 
  1. select rownum rn from all_objects where rownum<=xx; 

從all_objects等系統(tǒng)視圖中去獲取序列的方式,雖然簡單,但有一個致命的弱點是該視圖的sql非常復(fù)雜,嵌套層數(shù)很多,一旦應(yīng)用到真實案例中,極有可能碰到Oracle自身的bug,所以這種方式不考慮,直接pass掉。

2、9i之后,我們用connect by

 
 
 
  1. select rownum rn from dual connect by rownum<=xx; 

3、自從10g開始支持XML后,還可以使用以下方式:

 
 
 
  1. select rownum rn from xmltable(‘1 to xx’); 

接下來我們從序列大小,構(gòu)造時間等方面對比分析這兩種方式。

1、先看connect by的方法

 
 
 
  1. lastwinner@lw> select count(*) from (select rownum rn from dual connect by rownum<=power(2,19)); 
  2.  
  3. COUNT(*) 
  4.  
  5. ———- 
  6.  
  7. 524288 
  8.  
  9. 已用時間: 00: 00: 00.20 
  10.  
  11. lastwinner@lw> select count(*) from (select rownum rn from dual connect by rownum<=power(2,20)); 
  12.  
  13. select count(*) from (select rownum rn from dual connect by rownum<=power(2,20)) 
  14.  
  15.  
  16. 第 1 行出現(xiàn)錯誤: 
  17.  
  18. ORA-30009: CONNECT BY 操作內(nèi)存不足 

可見直接用connect by去構(gòu)造較大的序列時,消耗的資源很多,速度也快不到哪兒去。實際上2^20并不是一個很大的數(shù)字,就是1M而已。

但xmltable方式就不會耗這么多資源

 
 
 
  1. lastwinner@lw> select count(*) from (select rownum rn from xmltable(‘1 to 1048576’)); 
  2.  
  3. COUNT(*) 
  4.  
  5. ———- 
  6.  
  7. 1048576 
  8.  
  9. 已用時間: 00: 00: 00.95 

其實除了上述三種辦法,我們還可以使用笛卡爾積來構(gòu)造序列。如果換成笛卡爾連接的方式,那么構(gòu)造2^20時,connect by也ok

 
 
 
  1. lastwinner@lw> with a as (select rownum rn from dual connect by rownum<=power(2,10)) 
  2.  
  3. 2 select count(*) from (select rownum rn from a, a); 
  4.  
  5. COUNT(*) 
  6.  
  7. ———- 
  8.  
  9. 1048576 
  10.  
  11. 已用時間: 00: 00: 00.09 

我們試著將1M加大到1G,在connect by方式下

 
 
 
  1. lastwinner@lw> with a as (select rownum rn from dual connect by rownum<=power(2,10)) 
  2.  
  3. 2 select count(*) from (select rownum rn from a, a, a); 
  4.  
  5. COUNT(*) 
  6.  
  7. ———- 
  8.  
  9. 1073741824 
  10.  
  11. 已用時間: 00: 01: 07.37 

耗時高達1分鐘還多,再看看xmltable方式,考慮到1M的時候耗時就達到0.95秒,因此這里只測試1/16*1G,即64M的情況

 
 
 
  1. lastwinner@lw> select count(*) from (select rownum rn from xmltable(‘1 to 67108864’)); 
  2.  
  3. COUNT(*) 
  4.  
  5. ———- 
  6.  
  7. 67108864 
  8.  
  9. 已用時間: 00: 00: 37.00 

如果直接構(gòu)造到1G,那么時間差不多是16*37s這個級別。

但如果通過笛卡爾積+xmltable的方式來構(gòu)造。

 
 
 
  1. lastwinner@lw> select count(*) from (select rownum rn from xmltable(‘1 to 67108864’)); 
  2.  
  3. COUNT(*) 
  4.  
  5. ———- 
  6.  
  7. 67108864 
  8.  
  9. 已用時間:  00: 00: 37.00 

這時間和connect by的差不多。以上測試,總的可見,在構(gòu)造較大序列時,笛卡爾積的方式是***的,單純使用connect by會遭遇內(nèi)存不足,而單獨使用xmltable則會耗費較多的時間。

現(xiàn)在再看看基本用純表連接的方式來構(gòu)造同樣大小的序列,先來1M的

 
 
 
  1. lastwinner@lw> with b as (select 1 r from dual union all select 2 from dual), 
  2.  
  3. 2  c as (select rownum r from b,b,b,b,b, 
  4.  
  5. 3  b,b,b,b,b, 
  6.  
  7. 4  b,b,b,b,b, 
  8.  
  9. 5  b,b,b,b,b) 
  10.  
  11. 6  select count(*) from c; 
  12.  
  13. COUNT(*) 
  14.  
  15. ———- 
  16.  
  17. 1048576 
  18.  
  19. 已用時間:  00: 00: 00.33 

再來64M的

 
 
 
  1. lastwinner@lw> ed 
  2.  
  3. 已寫入 file afiedt.buf 
  4.  
  5. 1  with b as (select 1 r from dual union all select 2 from dual), 
  6.  
  7. 2  c as (select rownum r from b,b,b,b,b, 
  8.  
  9. 3  b,b,b,b,b, 
  10.  
  11. 4  b,b,b,b,b, 
  12.  
  13. 5  b,b,b,b,b, 
  14.  
  15. 6  b,b,b,b,b,b) 
  16.  
  17. 7* select count(*) from c 
  18.  
  19. lastwinner@lw> / 
  20.  
  21. COUNT(*) 
  22.  
  23. ———- 
  24.  
  25. 67108864 
  26.  
  27. 已用時間:  00: 00: 16.62 

這個速度并不快,但已經(jīng)比直接xmltable快了。

其實64M,即64*2^20可以表示為(2^5)^5*2,那我們來改寫一下64M的sql

 
 
 
  1. lastwinner@lw> with b as (select 1 r from dual union all select 2 from dual), 
  2.  
  3. 2  c as (select rownum r from b,b,b,b,b), 
  4.  
  5. 3  d as (select rownum r from c,c,c,c,c,b) 
  6.  
  7. 4  select count(*) from d; 
  8.  
  9. COUNT(*) 
  10.  
  11. ———- 
  12.  
  13. 67108864 
  14.  
  15. 已用時間:  00: 00: 04.53 

可以看到,從16s到4s,已經(jīng)快了很多。這個示例告訴我們,中間表c 在提高速度方面起到了很好的作用。

但在構(gòu)造到1G時,還是要慢一些

 
 
 
  1. lastwinner@lw> ed 
  2.  
  3. 已寫入 file afiedt.buf 
  4.  
  5. 1  with b as (select 1 r from dual union all select 2 from dual), 
  6.  
  7. 2  c as (select rownum r from b,b,b,b,b), 
  8.  
  9. 3  d as (select rownum r from c,c,c,c,c,c) 
  10.  
  11. 4* select count(*) from d 
  12.  
  13. lastwinner@lw> / 
  14.  
  15. COUNT(*) 
  16.  
  17. ———- 
  18.  
  19. 1073741824 
  20.  
  21. 已用時間:  00: 01: 11.48 

嘗試相對較快的寫法,多一層中間表

 
 
 
  1. lastwinner@lw> ed 
  2.  
  3. 已寫入 file afiedt.buf 
  4.  
  5. 1  with b as (select 1 r from dual union all select 2 from dual), 
  6.  
  7. 2  c as (select rownum r from b,b,b), 
  8.  
  9. 3  d as (select rownum r from c,c,c), 
  10.  
  11. 4  e as (select rownum r from d,d,d,c) 
  12.  
  13. 5* select count(*) from e 
  14.  
  15. lastwinner@lw> / 
  16.  
  17. COUNT(*) 
  18.  
  19. ———- 
  20.  
  21. 1073741824 
  22.  
  23. 已用時間:  00: 01: 06.89 

更快一點(思路,32^2=1024, 1G=2^30=(2^5)^6=((2^5)^2)^3 。)

 
 
 
  1. lastwinner@lw> ed 
  2.  
  3. 已寫入 file afiedt.buf 
  4.  
  5. 1  with b as (select 1 r from dual union all select 2 from dual), 
  6.  
  7. 2  c as (select rownum r from b,b,b,b,b), 
  8.  
  9. 3  d as (select rownum r from c,c), 
  10.  
  11. 4  e as (select rownum r from d,d,d) 
  12.  
  13. 5* select count(*) from e 
  14.  
  15. lastwinner@lw> / 
  16.  
  17. COUNT(*) 
  18.  
  19. ———- 
  20.  
  21. 1073741824 
  22.  
  23. 已用時間:  00: 01: 05.21 

這時候我們將2^5=32換成直接構(gòu)造出來的方式

 
 
 
  1. lastwinner@lw> ed 
  2.  
  3. 已寫入 file afiedt.buf 
  4.  
  5. 1  with b as (select rownum r from dual connect by rownum<=power(2,5)), 
  6.  
  7. 2  c as (select rownum r from b,b), 
  8.  
  9. 3  d as (select rownum r from c,c,c) 
  10.  
  11. 4* select count(*) from d 
  12.  
  13. lastwinner@lw> / 
  14.  
  15. COUNT(*) 
  16.  
  17. ———- 
  18.  
  19. 1073741824 
  20.  
  21. 已用時間:  00: 01: 05.07 

可見所耗費的時間差不多。

由此我們還可以得出,表連接的代價其實也是昂貴的,適當?shù)臏p少表連接的次數(shù),適當?shù)氖褂脀ith里的中間表,能有效提高系統(tǒng)性能。

再重復(fù)一下剛才構(gòu)造64M(2^26)的場景

 
 
 
  1. lastwinner@lw> ed 
  2.  
  3. 已寫入 file afiedt.buf 
  4.  
  5. 1  with b as (select 1 r from dual union all select 2 from dual), 
  6.  
  7. 2  c as (select rownum r from b,b,b,b,b, 
  8.  
  9. 3  b,b,b,b,b, 
  10.  
  11. 4  b,b,b,b,b, 
  12.  
  13. 5  b,b,b,b,b, 
  14.  
  15. 6  b,b,b,b,b,b) 
  16.  
  17. 7* select count(*) from c 
  18.  
  19. lastwinner@lw> / 
  20.  
  21. COUNT(*) 
  22.  
  23. ———- 
  24.  
  25. 67108864 
  26.  
  27. 已用時間:  00: 00: 16.62 

總共25次的表連接,1層嵌套,讓速度非常慢。提高一下(26=4*3*2+2*2),總共8次表連接,3層嵌套。

 
 
 
  1. lastwinner@lw> ed 
  2.  
  3. 已寫入 file afiedt.buf 
  4.  
  5. 1  with b as (select 1 r from dual union all select 2 from dual), 
  6.  
  7. 2  c as (select rownum r from b,b,b,b), 
  8.  
  9. 3  d as (select rownum r from c,c,c), 
  10.  
  11. 4  e as (select rownum r from d,d,b,b) 
  12.  
  13. 5* select count(*) from e 
  14.  
  15. lastwinner@lw> / 
  16.  
  17. COUNT(*) 
  18.  
  19. ———- 
  20.  
  21. 67108864 
  22.  
  23. 已用時間:  00: 00: 04.00 

效率提升4倍。要注意在這個案例中并非表連接越少越好,嵌套層數(shù)也是需要關(guān)注的指標。執(zhí)行計劃有興趣的同學自己去看吧,我就不列了,上例中,系統(tǒng)生成的中間表有3個。

最終結(jié)論,構(gòu)造較大序列時,例如同樣是構(gòu)造出64M的序列,oracle在處理時,用表連接的方式明顯占優(yōu)。但考慮到書寫的便利性,因此在構(gòu)造較小序列的時候,比如不超過1K的序列,那么直接用connect by或xmltable的方式就好了。

附:newkid 回復(fù)方法,表示更靈活,有興趣的同學可以嘗試:

 
 
 
  1. create or replace function generator (n pls_integer) return sys.odcinumberlist pipelined is 
  2. m pls_integer := trunc(n / 10); 
  3. r pls_integer := n – 10 * m; 
  4. begin 
  5. for i in 1 .. m loop 
  6. pipe row (null); 
  7. pipe row (null); 
  8. pipe row (null); 
  9. pipe row (null); 
  10. pipe row (null); 
  11. pipe row (null); 
  12. pipe row (null); 
  13. pipe row (null); 
  14. pipe row (null); 
  15. pipe row (null); 
  16. end loop; 
  17. for i in 1 .. r loop 
  18. pipe row (null); 
  19. end loop; 
  20. end; 
  21. alter function generator compile plsql_code_type = native; 
  22.  
  23. SQL> select count(*) from table(generator(67108864)); 
  24.  
  25. COUNT(*) 
  26. ———- 
  27. 67108864 
  28.  
  29. Elapsed: 00:00:06.68 
  30.  
  31. SQL> with b as (select 1 r from dual union all select 2 from dual), 
  32. 2  c as (select rownum r from b,b,b,b), 
  33. 3  d as (select rownum r from c,c,c), 
  34. 4  e as (select rownum r from d,d,b,b) 
  35. 5  select count(*) from e; 
  36.  
  37. COUNT(*) 
  38. ———- 
  39. 67108864 
  40.  
  41. Elapsed: 00:00:06.32 

文章標題:Oracle構(gòu)造序列的方法分析對比
轉(zhuǎn)載來源:http://www.dlmjj.cn/article/dheeijh.html