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

时间:2011-11-26 07:53:42

标签: django postgresql django-models

我的查询已经运行了大约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对象的客户端运行相同的查询,那么查询将再次快速返回。因此,当它们没有该客户端的Rank对象时,这似乎只是一个问题。

有什么想法吗?

版本: Postgres 9.1, Django 1.4 svn trunk rev 17047

2 个答案:

答案 0 :(得分:0)

迟到通常用于日期比较,也许你应该尝试按id desc排序然后限制为1。

答案 1 :(得分:0)

嗯,你没有显示实际的SQL,因此很难确定。但是,解释输出表明它认为找到匹配的最快方法是向后扫描“id”上的索引,直到找到有问题的客户端。

既然你说直到最近一直很快,这可能不是一个愚蠢的选择。但是,特定客户的记录总是有可能在此搜索的最末端。

所以 - 首先尝试两件事:

  1. 对相关表格运行分析,看看是否为计划者提供了足够的信息。
  2. 如果没有,请增加相关列上的统计数据(ALTER TABLE ... SET STATISTICS)并重新分析。看看是否可以。
  3. http://www.postgresql.org/docs/9.1/static/planner-stats.html

    如果仍然没有帮助,那么考虑(client,id)上的索引,并删除id上的索引(如果其他地方不需要)。这应该给你闪电般快速的答案。