我有一個Django(1.4.2)的數據模型,像這樣:優化訪問從select_for_update記錄
class CoreData(models.Model):
cdid = models.AutoField(primary_key=True,editable=False)
atr1 = # whatever
atr2 = # whatever
class EnvironData(models.Model):
cdid = models.ForeignKey(CoreData)
# etc
class TransactionData(models.Model):
edid = models.ForeignKey(EnvironData)
# etc
我需要有一個原子事務,其中我更新etc
交易數據:
tdo = TransactionData.objects.select_for_update().get(etc=criteria)
# process transaction
# modify tdo object
tdo.save()
到目前爲止,這麼好。但是,在process transaction
的過程中,我需要檢查CoreData.atr1
和CoreData.atr2
。
如果我通過tdo.edid.cdid.atr{1,2}
訪問那些,那麼我的理解是我將有一個額外的讀取數據庫查詢,因爲Django獲取缺失的數據。 (說實話,我不是100%肯定這只是一個;也可能是兩個 - 甚至六個,但我會懷疑這一點)。
另一方面,如果我結合select_related()
與select_for_update()
我不會只鎖定不需要(不應該)鎖定的數據,我還會爲tdo.save()
創建開銷。
第三種方法可能是通過獨立查詢獲取數據(與tdo
無關),如果使用select_related()
,將保證是單個數據庫查詢。另外,它可以使用values()
。
我認爲最後一種方法是最有效的,因爲查詢可以從EnvironData
對象開始,該對象的edid
已經作爲tdo.edid_id
。
我的觀點是否合理?有更好的方法嗎?
更新:這是完全沒關係訪問tdo.edid.cdid.atr{1,2}
獨立,甚至,他們可以在交易過程中發生變化,因爲它們是相互獨立的,它不要求他們保持整個交易的價值。 (謝謝@Uszy Wieloryba)
你最終做了什麼?我遇到過類似的情況,當我嘗試在'select_related'中使用'select_for_update'時,我在Postgres中遇到了一個錯誤,更不用說我也擔心這種性能(鎖定是我最需要的廣泛使用的功能)...這是棘手的東西:/ – orokusaki 2013-05-02 16:51:25
@orokusaki是的,這是_is_棘手的東西。我必須承認我還沒有優化它,所以生活在額外的數據庫中,這不是性能問題。我從來不喜歡'select_related' /'select_for_update'方法,感謝您的反饋。那麼看起來應該使用最後一種方法。你試過了嗎? – 2013-05-02 18:07:25
我還沒有。我的想法:忘記表現並努力簡化。如果它的N + 1問題(選擇相關),這是一個大問題,但如果它只有3-5個額外的查詢,我不會汗流it背。我寧願在給定的視圖中單獨選擇每條記錄進行更新,而不是在精神開銷「我必須記住在更新postgres時測試它」等等,如果它成爲真正的數據庫問題,另一個(更好?)解決方案可能是使用cache.add(...)來鎖定記錄。谷歌「使用memcached鎖定」。 – orokusaki 2013-05-02 22:42:54