Oracle千萬級數據入庫


Oracle千萬級數據入庫

最近在寫一個解析文件數據(txt、json、csv)並插入到數據庫中的腳本(基於Python和Oracle)。

剛開始做的時候就是只是用cx_Oracle模塊連接數據庫,建立insert SQL語句,然后循環給里面插。很簡單也很容易就實現了。

后面就遇到了唯一一個問題。就是大數據的解析處理。剛開始我用的是一個50多M的json數據,還有一個3M多的txt文件,這些都成功入庫了。緊接着馬上就遇到GB級別的json文件和txt文件。人就有點懵了,光怎么解析數據就花了兩天時間去研究(json數據格式很嚴謹,大文件情況先很難直接加載到內存中,最終使用了ijson模塊流式解析json文件解決了這個問題,txt文件還好說,可以一行一行的讀)。

后面簡單測試了一下,45萬條的json數據插入用了接近一個小時的時間,這是不可容忍的,只能說代碼質量太差。沒有考慮到性能的問題。

為了解決插入速度問題,首先想到的是多線程,將多線程用上去之后,幾分鍾就解決了問題,速度還能接受。到此為止就沒有接着往下研究了。這是我第一次修改后的主要代碼。就添加了一個多線程,看到插入速度還可以,就沒有繼續深究了。

sql = "INSERT INTO {}(ID, NAME) VALUES ( {} '{}')" .format(tableName, id, name)
cr.execute(sql)

with ThreadPoolExecutor(30) as executor:
   executor.map(func, data)
   #這里的data是一個可迭代的對象

然而現實就是如此的殘酷,接下來要入庫一個26GB甚至更大的txt文件,我的媽啊,大到notepad都加載不出來的那種,而且還有一個問題,這個文件大概是8000多萬條數據,插到一個表中表的數據量太大,對后續操作也不利。於是想到了將這個文件拆分,我在這里是拆分成了5個小的txt文件,每個txt文件的極限數據量設置為了2000w。接下來就是入庫的問題了。在網上查閱了一些資料,對我的代碼來說,可以在sql語句上進行優化。

將原來的參數傳遞改成了綁定變量的時候,原因是sql語句在數據庫中解析的時候消耗很多資源,分為硬解析和軟解析,有興趣的可以看一下,我這里只提一下我的優化過程。

sql = "INSERT INTO {}(ID, NAME) VALUES ( :ID, :NAME)" .format(tableName)
data = {"ID":1,
      "NAME":name}
cr.execute(sql, data)

這個我測試了170w的數據量,在使用變量傳參的情況下,插入170w數據花費了280s左右的時間,使用綁定的方式后變成了220s左右,大概省了一分鍾,但是這還是達不到要求的,這樣的速度對於將近億級別的數據量來說還是太low了。接下來怎么優化呢,多線程也使用過了,綁定變量也用過了,速度還是不太行,在網上再次查詢看到了批量插入的方式(其實這個很早就查到了,但是對我的數據來說,改造成這樣太麻煩也就沒有去使用),沒辦法了只能嘗試下這種優化方式了。

具體不再細說,直接上部分代碼吧。

sql = "INSERT INTO {}(ID, NAME) VALUES ( :ID, :NAME)" .format(tableName)
data = [(1, '小紅'), (2, '小明')]
cr.executemany(sql, data)

這里的data是一個列表,列表元素是元組,一個元組對應一條數據。

最后這個批量插入數據大大優化了插入速度,8000w數據大概十幾分鍾插完。很棒!

里面很多細節都沒有展開提到,因為我也不懂,就知道是這么用的。

這個就記錄下我的目前的三次優化過程吧。

1、多線程

2、綁定變量

3、批量數據入庫


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM