pg高性能服务器,如何充分利用单台服务器的性能将10亿级的json数据尽可能高效的插入postgresql?...
問題說明:
目前有一個文本格式的json數據,里面數據量約15億,每一行數據的格式都是固定的,插入前先要將json反序列化。運行環境為:windows server 2016,postgresql 10,Xeon E5506@2.13GHz,16G ddr3 1333,硬盤io上限約120MB/s,服務器板載RAID無法使用,用windows的帶區卷將兩塊硬盤組成一個卷,極限io也就170MB/s,性價比太低就沒做,直接使用了單塊硬盤。
思路和偽代碼:
基本思路,遍歷json文本,每100萬行文本做一次插入。插入時,將100萬行文本切割成小的分組用多線程的方式并行插入,每個線程每次都建立一個新的數據庫連接并處理一個分組。待100萬行文本處理完畢后再繼續遍歷json。
首先進行一些數據庫的基本優化:
創建數據庫和表,將表設置為unlogged
開啟postgresql的異步提交
# python偽代碼
def do_insert(rows):
# 每次插入都建立新的連接
conn=psycopg2.connect()
cur=conn.cursor()
# 遍歷rows,進行json反序列化,提取數據并構造sql語句,執行sql語句將rows一次性插入到數據庫
for row in rows:
v = json.loads(row)
insert_sql = "insert into ... values (%s,%s)" % (v[1], v[2])
cur.execute(insert_sql)
cur.commit()
conn.close()
def insert(Rows):
# 將Rows切割成100份,獲得100個rows,啟用n個do_insert線程
rows_list = split_list(Rows, 100)
pool = threadpool.ThreadPool(n)
requests = threadpool.makeRequest(do_insert, rows_list)
[pool.putRequest(req) for req in requests]
pool.wait()
def main():
# 載入json文本數據源
# 按行讀取,每讀取100萬行數據調用一次insert()
with open('import.json','r') as f:
index=0
Rows=[]
for line in f:
Rows.append(line)
index += 1
if index % 1000000 == 0:
insert(Rows)
目前嘗試了幾種參數組合,最終使用的是10個線程,每個線程插入1萬條,每100萬條做一次多線程批量插入耗時約2min,平均插入速度約8400條/s,跑完15億條數據大約要2天。
python執行到穩定狀態后:占用內存約1G,cpu占用率~30%,cpu線程數持續緩慢上升(似乎沒有回收線程)。
總的CPU使用率一直保持在~80%,其中python只占30%,另外有大量的postgres.exe進程,這部分應該占用了較多的cpu。硬盤寫io不固定,峰值30M/s、其余時間都是5M/s以下,速度明顯不行。
初步分析
對每個python語句的執行時間進行統計,發現主要的業務都在do_insert內,也就是具體執行插入操作的線程。不知道跟json.loads有無關系,還要進一步驗證。但是感覺python效率以及程序處理邏輯上還存在缺陷,所以沒有去進一步優化。
插入線程越多,postgresql進程會越多,這樣是否會導致cpu使用不平衡。
此外,是否還有其他可以優化的地方,無論是從語言上,還是處理邏輯上,還是數據庫配置上。
總結
以上是生活随笔為你收集整理的pg高性能服务器,如何充分利用单台服务器的性能将10亿级的json数据尽可能高效的插入postgresql?...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: cpu过热怎么处理 CPU过热应该怎么解
- 下一篇: 石家庄市长途汽车客运站到曲寨水泥厂服务大