2010-11-23 75 views
1

我有一個Django應用程序,它使用django-piston向內部客戶端發送XML提要。通常,這些工作非常好,但是我們有一些XML Feed,目前運行時間超過15分鐘。這會導致超時,並且提要變得不可靠。Django ORM:組織海量數據,正確的方式

我在想方法,我可以改善這種設置。如果它需要重新構造數據,那也是可能的。

下面是數據收集目前的樣子:

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 

顯然,該計劃的核心是做更多,但我只是指出問題所在。當我們有一個data列表中的300時,它變得不可靠並超時。

我已經試過什麼:

  • 獲取所有數據ID的集合,然後做一個大的查詢來獲取所有的MetadataItem的。最後,過濾我的循環中的那些。這是爲了保留一些它確實減少的查詢。
  • 使用.values()可以減少模型實例的開銷,這會加快速度但不會太快。

一個想法我在想一個更簡單的解決方案是寫入緩存的步驟。所以要減少超時;我會寫出前50個數據集,保存到緩存中,調整一些計數器,寫下50個數據集等。還需要思考這一點。

希望有人能幫助我帶着這個方向走向正確的方向。

+0

有沒有機會重組您的數據,以便您不必運行子查詢? – Evgeny 2010-11-23 23:22:15

回答

2

您發佈的代碼片段中存在的問題是,Django不包含自動通過反向關係連接的對象,因此您必須爲每個對象進行查詢。有一個很好的方法,作爲Daniel Roseman points out in his blog

如果這不能解決你的問題很好,你也可以看看試圖讓一個原始的SQL查詢一切......

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(): 
     # ... 

但是,如果可能,我會建議從web服務器之外的某處預先計算提要。如果結果小於1 MB,也許可以將結果存儲在memcache中。或者你可以成爲這個塊上的新孩子之一,並將結果存儲在像Redis這樣的「NoSQL」數據庫中。或者你可以將它寫入磁盤上的文件。

+0

謝謝你的答案..不幸的是,我已經嘗試過使用`select_related`幾乎和你描述的速度沒有太大變化一樣。有一些改進,但仍然是一場災難。 – Bartek 2010-11-23 21:12:59

+0

好的。預計算方法如何?考慮到你的限制,這可能嗎? – knutin 2010-11-23 21:14:02

0

如果你可以改變數據的結構,也許你也可以改變數據存儲?

允許某種結構(如CouchDB或MongoDB)的「NoSQL」數據庫在這裏實際上可能很有用。

比方說,你有一個文檔的每個數據項。該文件將有你的正常字段。您還將添加一個元數據列表的「元數據」字段。如何處理以下數據結構:

{ 
    'id': 'someid', 
    'field': 'value', 
    'metadata': [ 
     { 'key': 'value' }, 
     { 'key': 'value' } 
    ] 
} 

然後,您將能夠輕鬆獲取數據記錄並獲取所有元數據。要進行搜索,請將索引添加到「數據」文檔中的字段。

我在二郎/ OTP系統所使用的Mnesia這基本上是一個鍵值數據庫索引部分和助手上工作。我們大量使用嵌套記錄取得巨大成功。

我增加了這個作爲一個單獨的答案,因爲它是完全不同於其他。

0

另一個想法是用芹菜(www.celeryproject.com)這是一個python和django的任務管理系統。您可以使用它來異步執行任何長時間運行的任務,而不必保留主應用程序服務器。