2009-11-06 110 views
1

我有一些性能問題,因爲我做了很多查詢調用,我不知道如何減少。優化此django代碼?

user_item_rel_set是用戶和項目之間的m2m關係,顯示用戶爲特定項目支付了多少費用。每個項目可以有多個用戶和購買者,並且我試圖爲特定用戶獲取m2m關係。

 # find anything that you bought or used and how much you paid for it 
     u = User.objects.get(id=self.uid) 
     t = self.list.filter(user_item_rel__user__exact=u) 
     y = self.list.filter(buyer_item_rel__buyer__exact=u) 

     items = t | y 
     items = items.distinct() 
     u = User.objects.get(id=self.uid) 
     for t in items: 
      try: 
       t.price = t.user_item_rel_set.get(user=u).payment_amount 
      except: 
       t.price = -1 * t.buyer_item_rel_set.get(buyer=u).payment_amount 
     return items 

,並在另一個實例

for i in new_list: 
     if str(i.tag) not in x: 
      x[str(i.tag)] = 0 

     if houseMode == 0: 
      x[str(i.tag)] += float(i.user_item_rel_set.get(user__id__exact=self.uid).payment_amount) 
     else: 
      x[str(i.tag)] += float(i.price) 

回答

1

從模型中一些額外的代碼會有所幫助,因爲它很難看什麼「項目」的查詢集包含的內容。

我會盡力幫助反正...

因爲您建模用戶和項目之間的關係,也沒有必要每個項遍歷在查詢集時,你可以簡單地選擇那些子集對你有意思。

同樣,我在下面的應用程序邏輯有點困難,但我認爲你的查詢可以減少這種性質的東西:

# Find all the items where this user is the "user" 
user_items = items.filter(user_item_rel_set__user=u) 

# Find all the items where this user is the "buyer" 
buyer_items = items.filter(user_item_rel_set__buyer=u) 

我不太明白你爲什麼要分配這些值在循環中't.price',或者我將在該代碼上進行擴展。

如果這對您的性能沒有幫助,我建議您使用dumping your SQL queries to the console,以便您可以查看ORM背後的具體情況。在這樣的邏輯中,它不應該只用幾個SQL語句來計算。

此外,在貨幣值附近的任何位置使用浮點數據類型(float)通常是一個壞主意。浮點數據類型通常用於性能比精度更重要的科學應用。如果你在處理金錢問題,精確度幾乎總是比性能更重要,所以你使用的數據類型能夠精確表示,如decimal.Decimal 無處不在

編輯

鑑於評論,我建議用「關係」的對象,而不是在項目開始查詢。由於您的樣品不告訴我,類的名字,我會認爲這就是所謂的UserItem:

from django.db.models import Q 
from decimal import Decimal 

price = Decimal('0') 

# Get all UserItems where this user is the user or buyer 
interesting_items = UserItem.objects.filter((Q(user=u) | Q(buyer=u))) 
for ii in interesting_items: 
    if ii.user == u: 
     price += ii.payment_amount 
    elif ii.buyer == u: 
     price -= ii.payment_amount 
    else: 
     assert False, "Oops, this shouldn't happen" 

# Do something with 'price'... 

Django的「Q」功能可以讓你得到更多一點的顆粒與查詢。如果您需要根據物品的某個屬性進行過濾,請將其放在那裏。

在您的示例中,仍然讓我困惑的部分是爲什麼當明確許多用戶將共享該項目時,將「價格」分配給項目對象。

編輯2

您還可以使用aggregation API讓DBMS計算總和,如果這一切你感興趣的:

from django.db.models import Sum 
buyer_price = UserItem.objects.filter(item=i, user=u).aggregate(
       Sum('payment_amount'))['payment_amount__sum'] 
+0

因此項目具有一定的價格,它的M2M關係(user_item_rel)具有多少用戶爲該項目付費。我有一個用戶參與的項目清單(具體是你的代碼),我試圖檢索用戶爲每個項目支付了多少,但是如果不爲每一個項目敲擊數據庫,我都無法做到這一點。 – victor 2009-11-07 01:16:33

+0

因此'payment_amount'字段存儲在用戶和項目之間的關係對象上?我認爲M2M關係有其自己的模型? – 2009-11-07 01:48:02

+0

是的,就是這樣。 – victor 2009-11-07 01:57:18