Name Null? Type Comment
  ———— ——— ————- —————–
  CALL_ID NOT NULL NUMBER Primary key
  CALL_DATE NOT NULL DATE Non-unique index
  EMP_ID NOT NULL NUMBER
  CALL_TYPE NOT NULL VARCHAR2(12)
  DETAILS VARCHAR2(25)

逐條數(shù)據(jù)插入INSERT

數(shù)據(jù)導(dǎo)入的最簡(jiǎn)單方法就是編寫(xiě) INSERT 語(yǔ)句,將數(shù)據(jù)逐條插入數(shù)據(jù)庫(kù)。這種方法只適合導(dǎo)入少量數(shù)據(jù),如 SQL*Plus 腳本創(chuàng)建某個(gè)表的種子數(shù)據(jù)。該方法的最大缺點(diǎn)就是導(dǎo)入速度緩慢,占用了大量的 CPU 處理時(shí)間,不適合大批量數(shù)據(jù)的導(dǎo)入;而其主要優(yōu)點(diǎn)就是導(dǎo)入構(gòu)思簡(jiǎn)單又有修改完善的彈性,不需要多做其它的準(zhǔn)備就可以使用。如果你有很多時(shí)間沒(méi)法打發(fā),又想折磨一下數(shù)據(jù)庫(kù)和 CPU,那這種方法正適合你。

為了與其它方法做比較,現(xiàn)將十萬(wàn)條記錄通過(guò)此方法導(dǎo)入到 CALLS 表中,總共消耗 172 秒,其中導(dǎo)入進(jìn)程占用 CPU 時(shí)間為 52 秒。

逐條數(shù)據(jù)插入 INSERT,表暫無(wú)索引

為什么上一種方法占用了較多的 CPU 處理時(shí)間,關(guān)鍵是 CALLS 表中已創(chuàng)建了索引,當(dāng)一條數(shù)據(jù)插入到表中時(shí),Oracle 需要判別新數(shù)據(jù)與老數(shù)據(jù)在索引方面是否有沖突,同時(shí)要更新表中的所有索引,重復(fù)更新索引會(huì)消耗一定的時(shí)間。因此提高導(dǎo)入速度的好辦法就是在創(chuàng)建表時(shí)先不創(chuàng)建索引或者在導(dǎo)入數(shù)據(jù)之前刪除所有索引,在外部文件數(shù)據(jù)逐條插入到表中后再統(tǒng)一創(chuàng)建表的索引。這樣導(dǎo)入速度會(huì)提高,同時(shí)創(chuàng)建的索引也很緊湊而有效,這一原則同樣適用于位圖索引(Bitmap Index)。對(duì)于主要的和唯一的關(guān)鍵約束(key constraints),可以使之先暫時(shí)失效(disabling)或者刪除約束來(lái)獲得同樣的效果,當(dāng)然這些做法會(huì)對(duì)已經(jīng)存在的表的外鍵約束產(chǎn)生相關(guān)的影響,在刪除前需要通盤(pán)斟酌。

需要說(shuō)明的是,這種方法在表中已存在很多數(shù)據(jù)的情況下不太合適。例如表中已有九千萬(wàn)條數(shù)據(jù),而此時(shí)需要追加插入一千萬(wàn)條數(shù)據(jù),實(shí)際導(dǎo)入數(shù)據(jù)節(jié)省的時(shí)間將會(huì)被重新創(chuàng)建一億條數(shù)據(jù)的索引所消耗殆盡,這是我們不希望得到的結(jié)果。但是,如果要導(dǎo)入數(shù)據(jù)的表是空的或?qū)氲臄?shù)據(jù)量比已有的數(shù)據(jù)量要大得多,那么導(dǎo)入數(shù)據(jù)節(jié)省的時(shí)間將會(huì)少量用于重新創(chuàng)建索引,這時(shí)該方法才可以考慮使用。 加快索引創(chuàng)建是另一個(gè)需要考慮的問(wèn)題。為了減少索引創(chuàng)建中排序的工作時(shí)間,可以在當(dāng)前會(huì)話(huà)中增加 SORT_AREA_SIZE 參數(shù)的大小,該參數(shù)允許當(dāng)前會(huì)話(huà)在內(nèi)存的索引創(chuàng)建過(guò)程中執(zhí)行更多的排序操作。同樣還可以使用 NOLOGGING 關(guān)鍵字來(lái)減少因創(chuàng)建索引而生成的 REDO 日志量,NOLOGGING 關(guān)鍵字會(huì)對(duì)數(shù)據(jù)庫(kù)的恢復(fù)和 Standby 備用數(shù)據(jù)庫(kù)產(chǎn)生明顯的影響,所以在使用之前要仔細(xì)斟酌,到底是速度優(yōu)先還是穩(wěn)定優(yōu)先。

運(yùn)用這種方法,先刪除 CALLS 表的主鍵和不唯一的索引,然后逐條導(dǎo)入數(shù)據(jù),完成后重新創(chuàng)建索引( 表在導(dǎo)入數(shù)據(jù)前是空的)。該方法總共消耗 130 秒,包括重建索引的時(shí)間,其中導(dǎo)入進(jìn)程占用 CPU 時(shí)間為 35秒。

這種方法的優(yōu)點(diǎn)是可以加快導(dǎo)入的速度并使索引更加緊湊有效;缺點(diǎn)是缺乏通用性,當(dāng)你對(duì)表增加新的復(fù)雜的模式元素(索引、外鍵等)時(shí)你需要添加代碼、修改導(dǎo)入執(zhí)行程序。另外針對(duì) 7*24 在線(xiàn)要求的數(shù)據(jù)庫(kù)在線(xiàn)導(dǎo)入操作時(shí),刪除表的索引會(huì)對(duì)在線(xiàn)用戶(hù)的查詢(xún)有很大的性能影響,同時(shí)也要考慮,主要或唯一的關(guān)鍵約束條件的刪除或失效可能會(huì)影響到引用它們的外鍵的使用。

批量插入,表暫無(wú)索引

在Oracle V6 中 OCI 編程接口加入了數(shù)組接口特性。數(shù)組操作允許導(dǎo)入程序讀取外部文件數(shù)據(jù)并解析后,向數(shù)據(jù)庫(kù)提交SQL語(yǔ)句,批量插入 SQL 語(yǔ)句檢索出的數(shù)據(jù)。Oracle 僅需要執(zhí)行一次 SQL 語(yǔ)句,然后在內(nèi)存中批量解析提供的數(shù)據(jù)。批量導(dǎo)入操作比逐行插入重復(fù)操作更有效率,這是因?yàn)橹恍枰淮谓馕?SQL 語(yǔ)句,一些數(shù)據(jù)綁訂操作以及程序與數(shù)據(jù)庫(kù)之間來(lái)回的操作都顯著減少,而且數(shù)據(jù)庫(kù)對(duì)每一條數(shù)據(jù)的操作都是重復(fù)可知的,這給數(shù)據(jù)庫(kù)提供了優(yōu)化執(zhí)行的可能。其優(yōu)點(diǎn)是數(shù)據(jù)導(dǎo)入的總體時(shí)間明顯減少,特別是進(jìn)程占用 CPU 的時(shí)間。

需要提醒的是,通過(guò) OCI 接口確實(shí)可以執(zhí)行數(shù)據(jù)批量導(dǎo)入操作,但是許多工具和腳本語(yǔ)言卻不支持使用此功能。如果要使用該方法,需要研究你所使用的開(kāi)發(fā)工具是否支持 OCI 批量操作功能。導(dǎo)入程序需要進(jìn)行復(fù)雜的編碼并可能存在錯(cuò)誤的風(fēng)險(xiǎn),缺乏一定的彈性。

運(yùn)用上述方法,程序?qū)⑼獠繑?shù)據(jù)提取到內(nèi)存中的數(shù)組里,并執(zhí)行批量插入操作(100行/次),保留了表的刪除/重建索引操作,總的導(dǎo)入時(shí)間下降到 14 秒,而進(jìn)程占用 CPU 的時(shí)間下降到7秒,可見(jiàn)實(shí)際導(dǎo)入數(shù)據(jù)所花費(fèi)的時(shí)間顯著下降了 95%。

分享到

wangyao

相關(guān)推薦