2011-11-26 66 views
7

我有一個查詢已運行良好約2年。數據庫表大約有5000萬行,並且增長緩慢。上週我的一個疑問從幾乎立即返回到花費數小時才能完成。簡單的查詢工作多年,然後突然很慢

Rank.objects.filter(site=Site.objects.get(profile__client=client, profile__is_active=False)).latest('id') 

我已經將慢查詢範圍縮小到Rank模型。這似乎與使用latest()方法有關。如果我只是要求一個查詢集,它會馬上返回一個空的查詢集。

#count returns 0 and is fast 
Rank.objects.filter(site=Site.objects.get(profile__client=client, profile__is_active=False)).count() == 0 
Rank.objects.filter(site=Site.objects.get(profile__client=client, profile__is_active=False)) == [] #also very fast 

以下是運行EXPLAIN的結果。 http://explain.depesz.com/s/wPh

,並解釋分析一下:http://explain.depesz.com/s/ggi

我試着抽真空表,沒有任何變化。 「site」字段(ForeignKey)已經有一個索引。

奇怪的是,如果我爲另一個已經有與她的帳戶關聯的Rank對象的客戶端運行相同的查詢,那麼查詢將很快再次返回。所以,這似乎只是一個問題,當他們沒有該客戶端的對象。

任何想法?

版本: 的Postgres 9.1, Django的1.4 SVN主幹修訂版17047個

回答

0

那麼,你沒有顯示實際的SQL,所以很難確定。但是,解釋輸出表明它認爲找到匹配的最快方法是通過向後掃描「id」上的索引,直到找到有問題的客戶。

既然你說過它一直很快,直到最近,這可能不是一個愚蠢的選擇。但是,在搜索的最後端,總有一個特定客戶的記錄是正確的。

所以 - 首先要做兩件事情:

  1. 運行的問題上表分析,看看是否給規劃者足夠的信息。
  2. 如果不是,請增加相關列上的統計信息(ALTER TABLE ... SET STATISTICS)並重新分析。看看是否有這樣做。

http://www.postgresql.org/docs/9.1/static/planner-stats.html

如果仍然沒有幫助,再考慮上(客戶端ID)的索引,並在ID刪除索引(如果沒有其他地方需要用到)。這應該給你閃電般快速的答案。

+0

在WHERE字段中設置複合索引以及ORDER BY中的字段做了一個技巧。原來,查詢計劃員正在掃描整個索引,然後進行篩選。複合指數做到了訣竅。 – erikcw

0

latests通常用於日期比較,也許你應該嘗試用id DESC順序,然後限制在一塊。

+0

我試過了,而且也有類似的長時間延遲。當我查看由ORM生成的原始SQL時,兩者都產生相同的輸出。 – erikcw