2012-09-16 22 views
0

首先,這是我第一個使用SQLAlchemy的項目,所以我還是比較新的。選擇SQLAlchemy中的主鍵對象列表

我正在製作一個使用GTFS數據的系統。我有一個後端似乎能夠非常有效地查詢數據。

我想要做的是允許GTFS文件用新數據更新數據庫。我碰到的問題非常明顯,如果我試圖插入的數據已經在數據庫中,那麼我們在主鍵的唯一性上存在衝突。

出於效率的原因,我決定使用下面的代碼來進行插入,其中model是我想要插入數據的模型對象,data是預先計算並清除的要插入的字典列表。

for chunk in [data[i:i+chunk_size] for i in xrange(0, len(data), chunk_size)]: 
    engine.execute(model.__table__.insert(),chunk) 

想到兩種解決方案。

  1. 我找到了一種方法來做插入,這樣如果有碰撞,我們不關心,也不會失敗。我相信上面的代碼使用的是TableClause,所以我先在那裏查了一下,希望找到一個合適的替代品或標誌,但沒有運氣。

  2. 在我們執行數據清理之前,我們得到主鍵值列表,如果給定元素與主鍵匹配,我們跳過清理並插入值。我發現我能從Table.primary_key獲得PrimaryKeyConstraint,但我似乎無法獲取Columns,或者找到一種方法來只查詢特定列(在我的情況下是主鍵)。

如果我能找到辦法做到這一點,就應該足夠了。

在過去的幾個小時裏對這兩個問題進行了研究之後,我似乎無法找到任何一個。我希望以前有人可能會這樣做,並指出我的方向是正確的。

在此先感謝您的幫助!

更新1:有第三個選項我沒有提到上面。那就是清除數據庫中的所有數據,並重新插入它。我不希望這樣做,因爲即使使用小型GTFS文件,也容易插入數十萬個元素,而這似乎需要大約半小時的時間才能完成,這意味着如果這樣做會導致生產中出現大量宕機進行更新。

回答

1

使用SQLAlchemy,您只需創建模型類的新實例,並將其合併到當前會話中。 SQLAlchemy將檢測它是否已經知道該對象(來自緩存或數據庫),並在需要時將新行添加到數據庫。

newentry = model(chunk) 
session.merge(newentry) 

另請參見背景下,這個問題:Fastest way to insert object if it doesn't exist with SQLAlchemy

+0

哇,它的工作原理,但它肯定需要一個性能損失,不是嗎?到目前爲止,我似乎看到基於相同尺寸的2倍性能命中。 –

+0

這是因爲會話可能需要檢查*每個*合併對象,如果數據庫已經有一行它。如果你知道該行已經存在,則在'merge()'調用中加入'load = False'來防止發生這種檢查。 –

+0

另外,請注意,如果會話已經知道給定的主鍵,則不必再次檢查數據庫。對所有當前對象的查詢會給會話提供這些知識,這可能會顯着加速插入。 –