我有一个Django应用程序,它使用django-piston向内部客户端发送XML提要。通常,这些工作相当不错,但我们有一些目前运行超过15分钟的XML提要。这会导致超时,并且提要变得不可靠。
我正在考虑改进此设置的方法。如果它需要对数据进行一些重组,那也是可能的。
以下是数据收集目前的情况:
class Data(models.Model)
# fields
class MetadataItem(models.Model)
data = models.ForeignKey(Data)
# handlers.py
data = Data.objects.filter(**kwargs)
for d in data:
for metaitem in d.metadataitem_set.all():
# There is usually anywhere between 55 - 95 entries in this loop
label = metaitem.get_label() # does some formatting here
data_metadata[label] = metaitem.body
显然,该计划的核心是做得更多,但我只是指出问题所在。当我们有一个300的data
列表时,它就会变得不可靠并且超时。
我尝试了什么:
MetadataItem
。最后,在我的循环中过滤那些。这是为了保留一些它确实减少的查询。.values()
来减少模型实例开销,这确实加快了速度但不是很多。一个想法我认为一个更简单的解决方案是逐步写入缓存。所以减少时间;我会写出前50个数据集,保存到缓存,调整一些计数器,写下50个,等等。还需要思考这个。
希望有人能帮助我带领我走向正确的方向。
答案 0 :(得分:2)
您发布的代码中的问题是Django不包含通过反向关系自动连接的对象,因此您必须对每个对象进行查询。有一个很好的解决方法,如Daniel Roseman points out in his blog!
如果这不能很好地解决您的问题,您还可以尝试在一个原始SQL查询中获取所有内容...
答案 1 :(得分:1)
您可以通过首先获取所有数据ID然后使用select_related在单个大查询中获取数据及其元数据来进一步减少查询计数。这将大大减少查询的数量,但查询的大小可能不切实际/太大。类似的东西:
data_ids = Data.objects.filter(**kwargs).values_list('id', flat = True)
for i in data_ids:
data = Data.objects.get(pk = i).select_related()
# data.metadataitem_set.all() can now be called without quering the database
for metaitem in data.metadataitem_set.all():
# ...
但是,如果可能的话,我会建议从网络服务器之外的某个地方预先计算Feed。如果它小于1 MB,也许你可以将结果存储在memcache中。或者你可以成为街区中一个很酷的新孩子,并将结果存储在像Redis这样的“NoSQL”数据库中。或者你可以把它写到磁盘上的文件中。
答案 2 :(得分:0)
如果您可以更改数据结构,也许您也可以更改数据存储区?
允许某些结构的“NoSQL”数据库,如CouchDB或MongoDB,实际上在这里很有用。
假设每个数据项都有文档。该文档将具有您的正常字段。您还可以添加“元数据”字段,该字段是元数据列表。以下数据结构如何:
{
'id': 'someid',
'field': 'value',
'metadata': [
{ 'key': 'value' },
{ 'key': 'value' }
]
}
然后,您就可以轻松访问数据记录并获取所有元数据。要进行搜索,请将索引添加到“数据”文档中的字段中。
我在使用Mnesia的Erlang / OTP系统上工作,Mnesia基本上是一个带有索引和帮助器的键值数据库。我们大量使用嵌套记录取得了巨大成功。
我将此作为一个单独的答案添加,因为它与另一个完全不同。
答案 3 :(得分:0)
另一个想法是使用Celery(www.celeryproject.com),它是python和django的任务管理系统。您可以使用它来异步执行任何长时间运行的任务,而无需占用主应用服务器。