ORACLE PYTHON實戰 複製A表資料到B表

2022-09-13 15:27:09 字數 3374 閱讀 2616

最近在學習python ,看到了pythod的oracle,不僅可以一次fetch多條,也可以一次insert多條,想寫乙個複製a表資料到b表的程式來看看實際效率能不能提高。寫完發現,非常驚豔!效率提公升了近一倍! 當然可能會認為這個沒有實際意義,其實不然。

從a表複製資料到b表有很多中方法,一般直接insert即可:

insert into tablea select * from tableb ;

但是當資料量非常大時,到達上億水準的時候,這樣做就很鬱悶了,因為本身會跑很慢,又看不到進度,偶爾還會被資料庫因為回滾段不夠而悲劇。

所以,這種時候,我一般是用游標來做的:

declare

v_num number ;

begin

v_num:=0 ;

for v_cur in (select t.prod_inst_id , t.acc_num , t.user_name from cust30.prod_inst t where rownum <50000 ) loop

insert into test_prod_inst values (v_cur.prod_inst_id , v_cur.acc_num , v_cur.user_name) ;

v_num:=v_num+1 ;

if mod(v_num,50000) = 0 then

commit ;

end if ;

end loop ;

end ;

(也可以用fetch一次多條的方式:bulk  但是實際測試實際快不了多少)。現在的想法就是拿python替代這個,實際**如下:

#!/home/orashell/python27/bin/python

# -*- coding: utf-8 -*-

import os

import cx_oracle

#需要設定這個不然插入中文會亂碼

os.environ['nls_lang'] = 'simplified chinese_china.utf8'

#目的資料庫

trans_to_db = cx_oracle.connect('user/pass#@servicename')

#**資料庫

trans_from_db = cx_oracle.connect('user/pass#@servicename')

#開啟查詢游標

curselect = trans_from_db.cursor()

#開啟插入游標

curinsert = trans_to_db.cursor()

#根據游標生成插入的語句 需要根據已經開啟的游標、目的表名 輸出這樣的

#insert into test_prod_inst (prod_inst_id,acc_num,user_name) values(:1,:2,:3)

#輸入 fromcur 為乙個已經開啟的游標物件

#輸入 totable 為目的表名

#輸出 returnstr 為生成好的sql

def getinsertsql( fromcur ,totable ):

#習慣這樣做 :) 先生成乙個字串模板 再替換

returnstr = 'insert into '+totable+' (selectstr) values(insertstr)'

# 得到游標的描述 cx_oracle游標描述 本質為乙個元組(見下) 第一列為欄位名

#[('prod_inst_id', , 17, none, 16, 0, 0), ('acc_num', , 32, 96, none, none, 0), ('user_name', , 250, 750, none, none, 1)]

curdesc = fromcur.description

selectstr = ''

insertstr = ''

num=0

#拼好字串模板的 selectstr 以及 insertstr 部分

for i in curdesc:

num=num+1

selectstr=selectstr+i[0]+','

insertstr=insertstr+':'+str(num)+','

#去掉最後乙個','

selectstr=selectstr[0:len(selectstr) - 1]

insertstr=insertstr[0:len(insertstr) - 1]

#替換returnstr=returnstr.replace('selectstr',selectstr );

returnstr=returnstr.replace('insertstr',insertstr );

return returnstr

#實際執行的函式

def runmain():

#用乙個sql生成游標

curselect.execute('select t.prod_inst_id , t.acc_num , t.user_name from cust30.prod_inst t where rownum<10000 ')

#得到插入游標的

manyinserstr=getinsertsql(curselect, 'test_prod_inst')

#插入游標 prepare

curinsert.prepare(manyinserstr)

while true:

#fetch cx_oracle fetch 當fetch 一條的時候 得到的是一行資料的元組 但是如果是多行 得到的是乙個list

#所以 fetchone的結果不轉換 不能使用executemany

x=curselect.fetchmany(5000)

#插入curinsert.executemany(none, x)

#提交trans_to_db.commit()

#判斷退出

if len(x)==0:

break

#執行if __name__ == '__main__':

runmain()

trans_from_db.close

trans_to_db.close

本以為用這個會慢一些,因為實際上,這批資料庫是過了網路的(資料-本機-資料庫),而使用plsql是沒有使用網路。但是用這個插了5000萬資料,結果卻不是這樣,用了64秒,而用前文的第一種方式用了113秒,差不多是一倍的效率,這還是乙個資料庫兩個表的複製,如果是兩個資料庫,跨dblink會更加明顯。

原因我猜測是這麼兩個:

a:在實際insert的時候,cx_oralce拆成了多個執行緒去處理。如果考慮實際在特別大資料量的時候,plsql這邊也可以分為多個模處理,效率最終可能會卡在io上。

期待大神能夠解惑。

oracle python操作 增刪改查

oracle刪除 刪除表內容 truncate table new userinfo 刪除表drop table new userinfo 1.首先,python鏈結oracle資料庫需要配置好環境。1 python python 3.6.3 v3.6.3 2c5fed8,oct 3 2017,17...

專案實戰 ADS 層複購率統計

ads 層需要在 dws 層的資料上計算複購率,並儲存結果表。複購率可以從 dws 層的使用者購買商品明細表中進行計算。其中品牌 id 一級品類 id 一級品類名可以從使用者購買商品明細表中直接獲取,統計月份 統計日期也可以從當前時間獲取。剩下的購買人數 購買 2 次及以上人數 單次復購率 購買 3...

復變函式視覺化 復積分

復變函式的積分 z0 z1f z dz f z z int f z dz sum f delta z delta z z0 z1 f z dz f z z每一小段的復數值 乙個向量 乘以中間的某個值 積分法則 仿真實變函式積分 常數可以提出來 積分可以分段積分留數 用積分計算泰勒展開的係數 積分與路...