2011-11-10 209 views
1

我的代碼中有一個重複模式,其中模型有一個跟蹤其歷史/狀態的相關模型(一對多)。這個相關模型可以有許多對象表示模型狀態的時間點快照。Django ORM查詢找到所有沒有最近相關對象的對象

例如:

class Profile(models.Model): 
    pass 

class Subscription(models.Model): 
    profile = models.ForeignKey(Profile) 
    data_point = models.IntegerField() 
    created = models.DateTimeField(default=datetime.datetime) 

#Example objects 
p = Provile() 
subscription1 = Subscription(profile=p, data_point=32, created=datetime.datetime(2011, 7 1) 
subscription2 = Subscription(profile=p, data_point=2, created=datetime.datetime(2011, 8 1) 
subscription3 = Subscription(profile=p, data_point=3, created=datetime.datetime(2011, 9 1) 
subscription4 = Subscription(profile=p, data_point=302, created=datetime.datetime(2011, 10 1) 

我經常需要查詢這些模型,找出所有沒有在過去的3天或有類似的訂閱更新「檔案」的對象。我一直在使用子查詢來完成這件事:

q = Subscription.objects.filter(created__gt=datetime.datetime.now()-datetime.timedelta(days=3).values('id').query 
Profile.objects.exclude(subscription__id__in=q).distinct() 

問題是,當涉及大型表時,這是非常緩慢的。有這樣的查詢更有效的模式嗎?也許有些方法可以讓Django使用JOIN而不是SUBSELECT(好像去掉所有那些內嵌的循環會有幫助)?

我寧願使用ORM,但如果需要的話,我會願意使用.extra()方法甚至原始SQL,如果性能提升足夠引人注目。

我對Django 1.4alpha(SVN中繼)和Postgres 9.1運行。

回答

0
from django.db.models import Max 
from datetime import datetime, timedelta 

Profile.objects.annotate(last_update=Max('subscription__created')).filter(last_update__lt=datetime.now()-timedelta(days=3)) 

聚合(和註釋)是真棒醬,請參閱:https://docs.djangoproject.com/en/dev/topics/db/aggregation/

+0

我跑測試查詢和它非常緩慢(仍然在一小時後運行)。我在創建的字段上有一個索引。這個表雖然很大(5000萬行左右)。 – erikcw

+0

這就是您需要開始研究數據庫優化的關鍵。爲實例提供更多的RAM,將數據庫移動到它自己的實例,如果它尚未被隔離,甚至建立一個集羣,但是我剛剛給你的是最有效的你將會得到的優化查詢本身。 –

0

一個DB指數添加到created

created = models.DateTimeField(default=datetime.datetime, db_index=True) 

作爲一個經驗法則,即在使用的任何列查詢或排序的查詢應該被編入索引,除非編寫操作非常繁重(在這種情況下,您應該考慮使用單獨的搜索索引,也許)。

使用沒有索引的db列的查詢只有這麼快。如果您想更詳細地分析查詢瓶頸,請打開日誌記錄以獲取更長時間的運行語句(例​​如200毫秒及以上),並對長時間運行的查詢執行explain analyze(postgres)。

編輯: 我只在你的評論中看到你有一個領域的指數。在那種情況下,所有更多的理由來看看explain analyze的輸出。

  1. 確保索引真正被使用,並且充分擴展。
  2. 看是否Postgres的不必要地寫入磁盤,而不是使用內存

見 - 上查詢規劃http://www.postgresql.org/docs/current/static/runtime-config-query.html

也許這有助於爲介紹:http://blog.it-agenten.com/2015/11/tuning-django-orm-part-2-many-to-many-queries/

相關問題