简单的查询工作多年,然后突然很慢

简单的查询工作多年,然后突然很慢

问题描述:

我有一个查询已运行良好约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个

那么,你没有显示实际的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

latests通常用于日期比较,也许你应该尝试用id DESC顺序,然后限制在一块。

+0

我试过了,而且也有类似的长时间延迟。当我查看由ORM生成的原始SQL时,两者都产生相同的输出。 – erikcw