Python 许多人在Django行动缓慢

Python 许多人在Django行动缓慢,python,django,postgresql,Python,Django,Postgresql,我有两个简单的模型: class A(models.Model): name_a = models.CharField( _("name_a"), max_length=255) b = models.ManyToManyField( 'B', related_name='a', blank=True ) class B(models.Model): name_b = models.CharField(

我有两个简单的模型:

class A(models.Model):
name_a = models.CharField(
    _("name_a"),
    max_length=255)

    b = models.ManyToManyField(
        'B',
        related_name='a',
        blank=True
    )

class B(models.Model):
    name_b = models.CharField(
        _("name_b"),
        max_length=255)
我创建了1000条记录用于:

for i in range(1000):
    A.objects.create()
和B的3个对象:

for i in range(3):
    B.objects.create()
并通过m2m关系将b的每个对象与a的每个对象连接起来:

for a in A.objects.all().iterator(): 
    a.b.add(B.objects.all()[0]) 
    a.b.add(B.objects.all()[1]) 
    a.b.add(B.objects.all()[2])
现在,对于每个a对象,我想得到所有b对象:

import time 
start = time.time()
objects = A.objects.all()
for n in objects.iterator(): 
     list(n.b.all())
print(time.time() - start)

Output: 2.642864465713501
因此,仅对1000个对象执行此查询需要2秒以上的时间。表演太糟糕了。我在生产中有超过1000000件物品

我试图通过使用预回迁来提高性能:

import time 
start = time.time()
objects = A.objects.all().prefetch_related('b')
for n in objects.iterator(): 
     list(n.b.all())
print(time.time() - start)

Output: 2.684298038482666
但这毫无帮助。为什么速度如此之慢?如何提高性能?

来自Django文档

请注意,如果使用迭代器()运行查询,则将忽略与预回迁相关的()调用,因为这两种优化在一起没有意义


当运行这个程序时,使用sqlite大约需要0.7秒。如果我省略了为每个查询创建列表,时间会减少50%

关键是,你点击DB的次数与你点击
A
对象的次数相同。 因此,提高性能的最佳选择是减少查询数量。 但在这里,你到底打算做什么其实很重要。 由于这一点尚不清楚,从现在开始,或多或少只是猜测什么对你有用

可能只是在
A.objects.values\u list('id')
中迭代,然后查询
B
,因为您并不真正使用
A
对象:

bq = B.objects.all()
for a_id, in A.objects.values_list('id').iterator():
    list(bq.filter(b__id=a_id))  # maybe correct your related_name to 'a' so this would look a__id=a_id
print(time.time() - start)

如果您只想要与某些
a
对象相关的所有
b
对象,例如,所有带有
name\u a
的对象都包含
'foo'

B.objects.filter(b__name_a__contains='foo').all().distinct()

希望这些建议能有所帮助

这与您的实际问题无关,但您的
相关名称
可能应该是
'a'
而不是
'b'
。目光敏锐;-)谢谢你说得对,我没有说清楚我的意图。我需要序列化A和B对象。所以我需要一个ASerializer类。我认为序列化程序也只是在所有对象(如上面的代码)上循环并序列化它们。我发现serializer.data调用也需要2秒以上的时间。所以我只想通过手动进行数据库调用(使用python的list方法)来调试它。
B.objects.filter(b__name_a__contains='foo').all().distinct()