Django查询命中数据超过预期

时间:2012-04-21 19:27:54

标签: django django-queryset

我有 model.py ,如下所示:

class Muestraonline(models.Model):
    accessionnumber = models.ForeignKey(Muestra, related_name='online_accessionnumber')
    muestraid = models.ForeignKey(Muestra)
    taxonid = models.ForeignKey(Taxon, null=True, blank=True)
    collectedby = models.ForeignKey(Person, null=True, blank=True)
    locality = models.ForeignKey(Localitymayor, null=True, blank=True)

在我的 views.py:

def search(request):
    ...
        if genus:
           q &= Q(taxonid__genus__icontains = genus)
        if species:
           q &= (Q(taxonid__specificepithet__icontains = species | Q(taxonid__infraspecificepithet__icontains = species ))) 
        if island_group:
           q &= Q(locality__islandgroup__icontains = island_group)
        if island_name:
           q &= Q(locality__islandname__icontains = island_name)
        if collection_acronym:
           q &= Q(muestraid__collectionid__collectioncode__icontains = collection_acronym)
        if accession_number:
           q &= Q(muestraid__accessionnumber = accession_number)
        if last_name:
           q &= Q(collectedby__verbatimname__icontains = last_name)
        if collection_number:
           q &= Q(muestraid__collectionnumber = collection_number)

        query_set = Muestraonline.objects.filter(q).order_by('taxonid__genus', 'taxonid__specificepithet', 'muestraid') 

        query_set = list(query_set) 

在我的模板中我做了类似的事情:

{% for specimen in items.object_list %}
 {{ specimen.taxonid.genus }} -- {{ specimen.taxonid.specificepithet }}
 {{ specimen.muestraid_id }}
 {{ specimen.accessionnumber_id }}
 {{ specimen.muestraid.localitymayorid.islandname }}
{% endfor %}

当我使用django调试工具栏查看结果时,我发现db的初始搜索查询非常繁重,但我认为给定结构(不会改变)是不可避免的。但是,当我在模板中迭代时,每个对象也会进行查询以获取taxonlocality数据。

我认为使用select_related()可以避免这种情况,但它实际上会降低请求速度(通过在初始查询中添加一些连接),并且查询总数保持不变。

我的问题是:如何最小化数据库的命中率?例如,我可以将查询集评估一次,然后在模板迭代期间从中提取结果吗?正如您所看到的,我已经尝试将query_set作为列表进行投射,但这没有任何区别。

这里的任何指导都将非常感谢。

1 个答案:

答案 0 :(得分:1)

我建议您尝试告诉select_related要遵循哪些确切的关系。添加select_related使查询过慢的事实可能是因为它跟随不需要的关系。请尝试以下方法:

query_set = Muestraonline.objects.filter(q).order_by('taxonid__genus', 'taxonid__specificepithet', 'muestraid').select_related('taxonid', 'muestraid__localitymayorid')

我发现很难相信在将select_related添加到您的查询后,它仍然在为每个实例访问数据库 - 您确定要评估正确的QuerySet吗?

此外,在将QuerySet提供给分页器之前将其转换为列表并不是最好的选择 - 它最终会从数据库中获取所有内容,然后将大部分内容丢弃,因为您只显示一小部分。如果您将QuerySet直接提供给paginator,它会限制QuerySet本身只提取您想要的项目。