2014-11-24 78 views
3

問題:對於一個Connnection對象的執行功能,可以使用一臺發電機返回字典而不是字典做一個「executemany」的列表中插入?SQLAlchemy的exectutemany與發電機

詳細信息:我試圖通過該core expressions努力學習SQLAlchemy的。作爲測試,我有一個相當大的數據集,從文件訪問通過一個迭代中,我試圖轉移到一個PostgreSQL表,但插入各個行是相當緩慢(參見下文實施例1)。按照documentation,如果詞典列表中傳遞,而不是一個單一的字典Connnection對象的​​功能將做一個executemany()的等價物。我做了一些快速測試,實際上這種方法對插入組來說要快得多。不幸的是,我的大數據集,我不能在內存中創建詞典的完整列表,因此我的問題...

例1:以下(僞)代碼是大量數據

的速度很慢
from sqlalchemy import MetaData, Table, Column 

metadata = MetaData() 
data = Table('data', metadata, Column...) 

engine = sql.create_engine('postgresql://user:[email protected]/testdb') 
metadata.create_all(engine) 

conn = engine.connect() 
ins = data.insert() 
for datum in large_data_iterator: 
    datum_dict = do_some_proc(datum) 
    conn.execute(ins, datum_dict) 

由於執行可以擁有多個值,這將是很好,以取代最後for環路與以下生成版本:

def datagen(iterator): 
    for datum in large_data_iterator: 
     datum_dict = do_some_proc(datum) 
     yield datum_dict 

conn = engine.connect() 
ins = data.insert() 
conn.execute(ins, datagen(large_data_iterator)) 

然而,這引起了以下異常:AttributeError的:「名單」對象沒有屬性'k餘仁生。

有誰知道是否有可能讓發電機版本的工作?或者更好的方法來做到這一點也很好。謝謝!

注:我測試其產生組塊作爲字典(下圖)的列表的改性發生器表達,它比個人執行得更快。但是,我不知道如何選擇最佳數量的塊,我擔心發生器代碼增加的複雜性使其可能更容易出錯。 (但是,如果它是唯一的出路......)

def datagen(iterator): 
    output = [] 
    N = 0 
    for datum in large_data_iterator: 
     datum_dict = do_some_proc(datum) 
     output.append(datum_dict) 
     N += 1 
     if N == 100: # or whatever 
      yield output 
      N = 0 
      output = [] 
    if output != []: 
     yield output 

回答

0

execution_optionsConnection,內搭一件stream_results參數,但unforutunately在底部它說,「該標誌目前由psycopg2只聽懂方言「,儘管還有其他支持流媒體的驅動程序(例如oursql)。

在sqlalchemy中完全支持它之前,您可以輕鬆地編寫一個幫助函數到break any iterable into chunks以避免修改您的生成器的錯誤傾向性。