2013-04-03 57 views
2

爲什麼這個查詢在Django使用MySQL緩慢? 我有三個模型,我正在過濾,與OneToOne和ForeignKey彼此相關。以下查詢在我的數據庫中大約有60k行需要大約300秒才能完成。Django的雙內部連接與MySQL緩慢

resutls = A.objects.filter(b__c__candy__icontains="gummybears") 
results # <-- 300 seconds 

在應用程序的模型:

class A(models.Model): 
    b = models.OneToOneField(B, default=None) 
    a_charfield = models.CharField(max_length=40, default='') 

class B(models.Model): 
    b_charfield = models.CharField(max_length=40, default='') 
    primary_id = models.CharField(max_length=40, unique=True, primary_key=True, default='', null=False) 

class C(models.Model): 
    b = models.ForeignKey('B') 
    candy = models.CharField(db_index=True, max_length=40, default='') 

打印result.query顯示MySQL查詢爲(我的組合列名*):我有兩個工作

SELECT * 
FROM `app_a` 
INNER JOIN `app_b` ON (`app_a`.`b_id` = `app_b`.`primary_id`) 
INNER JOIN `app_c` ON (`app_b`.`primary_id` = `app_c`.`b_id`) 
WHERE `app_c`.`candy` LIKE %gummybears% 
ORDER BY `app_a`.`id` DESC 

解決方案。

  1. 得到B的結果作爲values_list並作爲過濾器使用arg至A. https://docs.djangoproject.com/en/dev/ref/models/querysets/#in性能考慮

    resutls = A.objects.filter(b__in=list(B.objects.filter(c__c_charfield__icontains="candy").values_list('pk', flat=True)) 
    
  2. 切換到PostgreSQL。雙內連接工作< 1秒
+1

使用情況下的文檔還'select_related()' – catherine 2013-04-04 02:03:38

+0

你能運行使用MySQL錯誤的解釋?也許你錯過了其中一個外鍵的索引? – Arjen 2013-05-18 10:07:02

回答

0

以下代碼中的前導%強制查詢執行全表掃描而不是使用索引。如果糖果表不適合內存需要一段時間。

WHERE `app_c`.`candy` LIKE %gummybears% 

B-Tree Index Characteristics