2017-09-26 224 views
0

我一直在教自己的Django和SQL,我注意到的一件事是,当处理大型表(> 1,000,000条记录)时,指定一个排序非常缓慢。例如:数据库查询:Django的快速替代方法order_by()

Model.objects()[offset:limit]

可能需要几毫秒的时间,假设offsetlimit是一个足够小的范围内。但是:

Model.objects()[offset:limit].order_by('name')

可能需要10或20秒,取决于表中的行的数目。我明白为什么会这样;必须检查所有行以确保返回正确的结果。我也明白,这更多的是SQL问题,而不是Django问题,我用Django代码解释它更容易。

所以这是我的问题:

  1. 因为我看到Django的生产网站显示下令从非常大的表中的数据,他们是如何做到这一点,而不每个查询回吐>10秒?

  2. 我解决了第一个问题后,如何扩展我的Django应用程序以允许多列(名称,日期,值等)的排序?

我的直觉说,回答第一个问题是插入我希望它显示,这样在执行查询时没有顺序是必要的顺序每个记录,但似乎难以维持。

此外,这意味着,唯一的答案我能想到的第二个问题涉及创建多个表,均有不同的列排序,然后访问它像这样:

if request.GET['order'] == name: 
    result_set = NameOrderedModel.objects()[offset:limit] 
elif request.GET['order'] == value: 
    result_set = ValueOrderedModel.objects()[offset:limit] 

的代码,这些查询是相当简单的,但我不寒而栗,想到要建立一个数据库需要多少工作,以便这样的查询是可能的。有没有更好的办法?

+0

您是否尝试在Django ORM中编写原始SQL查询?这可以提高您的查询性能多倍。而抵消,限制和order_by肯定会快得多。 –

+1

这个问题很可能是(缺乏)索引。只需在'name'字段中添加'db_index = True'并且'migrate'来查看是否有帮助。 – Selcuk

回答

1

是的,不应该那么慢。尝试将一个索引添加到“名称”列。这绝对应该回到毫秒范围内。对于那么多行,应该预期一个索引。

很少有其他建议:ORDER_BY后限制,像这样:

1)为了提高可读性,我会做偏移

Model.objects.all().order_by('name')[offset:limit] 

2)如果你仍然有速度问题,打印执行SQL语句:

data = Model.objects.all().order_by('name')[offset:limit] 
print data.query 

并在查询工具中执行一些故障排除,或者如果您仍然卡住,请尝试粘贴回来。