为什么在使用 MySQL 的 Django 中这个查询很慢?我使用 OneToOne 和 ForeignKey 过滤了三个相互关联的模型。在我的数据库上进行以下大约 60k 行的查询需要大约 300 秒才能完成。
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
我有两个可行的解决方案。
从 B 获取结果作为 values_list 并用作 A 的过滤器 arg。 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))
- 切换到postgresql。双内连接工作 < 1 秒