日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

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

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
從一個(gè)開(kāi)發(fā)需求的解決方案看Oracle臨時(shí)表

一、開(kāi)發(fā)需求 

成都創(chuàng)新互聯(lián)公司是專業(yè)的渭城網(wǎng)站建設(shè)公司,渭城接單;提供成都做網(wǎng)站、網(wǎng)站建設(shè),網(wǎng)頁(yè)設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行渭城網(wǎng)站開(kāi)發(fā)網(wǎng)頁(yè)制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛(ài)的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來(lái)合作!

最近有一個(gè)開(kāi)發(fā)需求,大致需要先使用主表,或主表和幾張子表關(guān)聯(lián)查詢出 ID(主鍵) 及一些主表字段,然后再用這些 ID 查找最多 10 張表中對(duì)應(yīng)的記錄,主表記錄數(shù)大約 2000 萬(wàn),每張子表的記錄數(shù)均為百萬(wàn)以上,最多可能會(huì)有 5000 萬(wàn),主表一條數(shù)據(jù)可能對(duì)應(yīng)子表多條數(shù)據(jù)?,F(xiàn)在開(kāi)發(fā)使用的邏輯是:

1. 使用條件查詢主表或主表和幾張子表 (不同場(chǎng)景) 符合條件的主表記錄 ID 值及其他一些主表字段項(xiàng)。

2. 利用這些主表 ID 值,分別和幾張子表使用 IN 子句,查詢出子表中符合條件的記錄項(xiàng)。有幾張子表,就執(zhí)行幾次 SQL 語(yǔ)句。

這么做的弊端是

由于 (1) 查出的 ID 值最多可能會(huì)有 100 個(gè)以上,因此子表使用 IN 子句的時(shí)候很有可能導(dǎo)致 CBO 選擇全表掃描,雖然從理論上說(shuō),一條 SQL 未必適用索引掃描效率就一定高,CBO 一定是基于現(xiàn)有的統(tǒng)計(jì)信息選擇一條成本值***的執(zhí)行計(jì)劃,但一張***甚至***的表,全表掃描的效率可想而知 (這兒我們不較真,可能通過(guò) SSD、Exadata 硬件層面的使用能提高全表掃描的效率,此處只討論一般存儲(chǔ)條件下可行的方案)。另外,就是場(chǎng)景需要幾張子表,就會(huì)執(zhí)行幾次 SQL,一個(gè)場(chǎng)景下可能需要執(zhí)行很多次 SQL 語(yǔ)句。

綜合需求,可能至少有以下幾種改進(jìn)方案

1. 使用一條 SQL 完成上述需求。

(1.1) 主表和所有子表采用 join 關(guān)聯(lián)的方式。

兩表兩表做 join,又由于主子表之間是一對(duì)多的關(guān)系,很可能造成結(jié)果集因?yàn)榈芽柗e變得很大,應(yīng)用處理出現(xiàn)內(nèi)存溢出的錯(cuò)誤。

(1.2) 使用 union all 的方式關(guān)聯(lián)子表,作為 VIEW,然后和主表做關(guān)聯(lián),這是羅大師推薦的方式,例如:

 
 
 
  1. SELECT A.ID, A.NAME  
  2. FROM  
  3. T_ZHUBIAO A,  
  4. (SELECT ID, NAME FROM T_ZIBIAO1 UNION ALL SELECT ID, NAME FROM T_ZIBIAO2) B  
  5. WHERE A.NAME = 'A' AND A.ID = B.ID; 

和 (1.1) 的區(qū)別就是每一張子表的檢索都是一次獨(dú)立的索引唯一掃描,所有子表關(guān)聯(lián)后作為 VIEW,和主表做一次嵌套循環(huán)連接。但據(jù)了解,需求中每張子表的字段基本都不相同,有的子表選擇字段有幾十個(gè),這么一來(lái),使用這種 UNION ALL 需要檢索字段類(lèi)型相同,開(kāi)發(fā)拼接起來(lái)就比較費(fèi)勁,不靈活。

2. 將 (1) 的結(jié)果集存入一張臨時(shí)表 (temporary table,不是應(yīng)用自行處理的普通表),相當(dāng)于臨時(shí)結(jié)果集,每次子表都是和這張臨時(shí)表做兩表關(guān)聯(lián)查詢,這么做可以避免因?yàn)?IN 值太多導(dǎo)致的低效檢索,同時(shí)由于兩表關(guān)聯(lián)字段均為主鍵或外鍵 (設(shè)置索引),可以使用索引掃描檢索,采用交易級(jí)別控制的臨時(shí)表,可以在完成本次交易后讓 Oracle 自動(dòng)清空數(shù)據(jù),同時(shí) session 之間數(shù)據(jù)隔離。

3.(1) 不變,只是 (2) 中每次子表查詢,由應(yīng)用控制,例如每 30 個(gè) IN 值執(zhí)行一條 SQL 語(yǔ)句,將一次子表查詢拆分為若干次查詢,好處是每次可以使用外鍵索引掃描檢索結(jié)果集,壞處就是無(wú)形中又多了 N 次 SQL 語(yǔ)句的執(zhí)行。

綜上三種方案,(1) 由于潛在的結(jié)果集過(guò)大的問(wèn)題以及靈活性問(wèn)題,被開(kāi)發(fā)否了,目前采用的是方案 (3),因?yàn)槠鋵?duì)開(kāi)發(fā)的改造較小,僅需要拆分 IN 語(yǔ)句,如果檢索效率較高,測(cè)試結(jié)論符合非功能要求,就采用這種方式,若不滿足要求,則會(huì)考慮使用方案 (2)。

就我來(lái)說(shuō),如果能滿足需求,方案 1 是***的,使用合適的索引完成一次檢索,減少了應(yīng)用和數(shù)據(jù)庫(kù)之間的交互次數(shù),但可能這種業(yè)務(wù)需求確實(shí)很復(fù)雜,獲取信息方面確實(shí)要求比較高。其次是方案 2,雖然子表執(zhí)行 SQL 次數(shù)未變,但通過(guò)臨時(shí)表,可以保證每次檢索均可以使用索引快速定位,避免大表的全表掃描,同時(shí)臨時(shí)表特性對(duì)應(yīng)用幾乎透明。方案 3,唯一的好處就是避免了大表的全表掃描,但代價(jià)是會(huì)多一些 SQL 交互,至于究竟是否可以彌補(bǔ)性能上的差異,只能待性能測(cè)試的結(jié)論來(lái)看了。

如果各位對(duì)上述需求有更好的解決方案,或是上述方案仍有問(wèn)題,還請(qǐng)不吝指正!

二、臨時(shí)表介紹和實(shí)驗(yàn) 

需要緩存中間結(jié)果集的場(chǎng)景,可以考慮使用臨時(shí)表,因?yàn)榕R時(shí)表中的數(shù)據(jù)是 session 級(jí)別私有,每個(gè) session 僅能看見(jiàn)和修改自己的數(shù)據(jù),在 session 結(jié)束的時(shí)候,表中數(shù)據(jù)會(huì)被自動(dòng)刪除,無(wú)需應(yīng)用操作。創(chuàng)建臨時(shí)表使用的是 CREATE GLOBAL TEMPORARY TABLE 語(yǔ)法,ON COMMIT 子句則決定了表數(shù)據(jù)是交易級(jí)別還是 session 級(jí)別,默認(rèn)是交易級(jí)別??梢詫?duì)臨時(shí)表創(chuàng)建索引、視圖或觸發(fā)器。

ON COMMIT 子句的兩種參數(shù)區(qū)別如下:

臨時(shí)表中的數(shù)據(jù)默認(rèn)存儲(chǔ)于默認(rèn)的臨時(shí)表空間,可以創(chuàng)建過(guò)程中指定其他的臨時(shí)表空間。臨時(shí)表的數(shù)據(jù)和索引在定義的時(shí)候不會(huì)分配段,只有使用 INSERT(CTAS) 插入語(yǔ)句的時(shí)候,才會(huì)開(kāi)始分配段空間。

創(chuàng)建交易級(jí)別臨時(shí)表:

 
 
 
  1. SQL> create global temporary table test (id number, name varchar2(10)) on commit delete rows;

查看表屬性,TEMPORARY 指定為 Y,說(shuō)明是臨時(shí)表,沒(méi)有 tablespace_name 參數(shù)值,說(shuō)明不是使用普通表空間存儲(chǔ)。

 
 
 
  1. SQL> select table_name, tablespace_name, temporary from dba_tables where owner='BISAL'; 
  2. TABLE_NAME  TABLESPACE_NAME  TEM 
  3. ---------------- --------------------        --- 
  4. TEST                                            Y

session 1 執(zhí)行:

 
 
 
  1. SQL> insert into test values(1, 'a'); 
  2. SQL> select * from test; 
  3. ID NAME 
  4. -- ----  
  5. 1 a

session 2 執(zhí)行:

 
 
 
  1. SQL> select * from test; 
  2. no rows selected

說(shuō)明臨時(shí)表數(shù)據(jù) session 級(jí)別隔離,

session 1 執(zhí)行:

 
 
 
  1. SQL> commit; 
  2. SQL> select * from test; 
  3. no rows selected

執(zhí)行 commit 結(jié)束交易,Oracle 會(huì)自動(dòng)刪除臨時(shí)表中數(shù)據(jù)。

創(chuàng)建 session 級(jí)臨時(shí)表:

 
 
 
  1. SQL> create global temporary table test (id number, name varchar2(10)) on commit preserve rows;

表屬性相同:

 
 
 
  1. SQL> select table_name, tablespace_name, temporary from dba_tables where owner='BISAL'; 
  2. TABLE_NAME   TABLESPACE_NAME  TEM 
  3. --------------     --------------------       --- 
  4. TEST                                             Y

session 1 執(zhí)行:

 
 
 
  1. SQL> insert into test values(1, 'a'); 
  2. SQL> select * from test; 
  3. ID NAME 
  4. -- ----  
  5. 1   a

session 2 執(zhí)行:

 
 
 
  1. SQL> select * from test; 
  2. no rows selected

session 1 執(zhí)行:

 
 
 
  1. SQL> commit; 
  2. SQL> select * from test; 
  3. ID NAME 
  4. -- ----  
  5. 1   a

執(zhí)行 commit 后,數(shù)據(jù)未刪除。退出當(dāng)前 session 再登陸,發(fā)現(xiàn)數(shù)據(jù)已被刪除了:

 
 
 
  1. SQL> select * from test; 
  2. no rows selected

總結(jié)

臨時(shí)表使用起來(lái)其實(shí)很簡(jiǎn)單,除了一些語(yǔ)法上和普通建表語(yǔ)句有些不同,對(duì)應(yīng)用來(lái)說(shuō)就可以當(dāng)作普通表使用,但其實(shí)還是有一些細(xì)節(jié)需要注意:

1. 臨時(shí)表默認(rèn)使用的是默認(rèn)臨時(shí)表空間,如果應(yīng)用會(huì)有很多排序等需要耗費(fèi)臨時(shí)表空間的場(chǎng)景,而且臨時(shí)表使用頻率很高,那么為了避免互相影響,可以考慮為臨時(shí)表建一個(gè)獨(dú)立的臨時(shí)表空間。

2. 如果使用 session 級(jí)別的臨時(shí)表,且應(yīng)用使用了連接池,則需要確保應(yīng)用完成一次交易過(guò)程中使用的是同一 session,避免違反臨時(shí)表使用規(guī)則。


文章題目:從一個(gè)開(kāi)發(fā)需求的解決方案看Oracle臨時(shí)表
文章網(wǎng)址:http://m.5511xx.com/article/dhjjijc.html