2011-05-11 39 views
0

多少數據庫查詢將以下代碼執行:查詢集緩存:過濾器被解僱後執行GET

q = SomeModel.objects.filter(pk__in=ids) 
print q # The actual query is executed and the result 
      # set evaluated 
m = q.get(pk=ids[0]) 
print m # Does it reuse the evaluated result set 
      # or does it hit the database the second time? 

回答

1

由於查詢集懶洋洋地評估,如果你這樣做:

q = SomeModel.objects.filter(pk__in=ids) 

...立即folllowed(即不使用print):

m = q.get(pk=ids[0]) 

您將與一個SQL q結束了uery。它會將AND與第一個查詢結合在一起。以這種方式繼續添加到查詢集是安全的。在Django 1.3日誌改版,您可以在交互式控制檯得到很好的記錄:

>>> import logging 
>>> l = logging.getLogger('django.db.backends') 
>>> l.setLevel(logging.DEBUG) 
>>> l.addHandler(logging.StreamHandler()) 

,這將給你這種只要是執行的實際查詢調試信息的:

(0.013) SELECT "someapp_somemodel"."id", "someapp_somemodel"."question", "someapp_somemodel"."pub_date" FROM "someapp_somemodel" WHERE ("someapp_somemodel"."id" IN (0, 1) AND "someapp_somemodel"."id" = 0); args=(0, 1, 0) 

不要在已過濾的查詢集上使用get。如果你想要的模型在你的查詢集中,使用一個Python表達式(比如列表解析或者filter或者其他類型)來將模型實例從你的查詢集中取出,並避免再次擊中數據庫(或者多次你遍歷一個id列表)。

+0

請注意,這些「印刷品」同時模擬評估結果集。這不是我的實際代碼,它只是一個簡約的例子。我對所描述的情況特別感興趣,其中'filter'和'get'通過評估第一個查詢集來分隔。 – julkiewicz 2011-05-11 15:58:19

+2

@julkiewicz只需使用python表達式來獲取所需的模型實例。你可以例如做'過濾(lambda x:x.id == 3,qs)'並且使用'id == 3'獲取模型實例,而不用再次敲擊數據庫。打開控制檯中的日誌記錄並進行試驗,您將看到在特定情況下何時/如何執行查詢,並能夠改進您的方法。 – zeekay 2011-05-11 16:06:40