Django ORM实在很慢地遍历QuerySet

时间:2019-07-15 12:55:49

标签: python django django-models django-orm

我正在研究一个新项目,因此必须快速构建几页的轮廓。

我导入了要搜索的280k产品目录。我选择了Whoosh和Haystack进行搜索,因为我在以前的项目中使用了它们。 我为索引添加了定义,并开始了该过程。但是,似乎Django在QuerySet上真的非常真的慢。 最初,我认为编制索引要花费超过24小时的时间-这似乎很荒谬,因此我测试了其他一些内容。现在,我可以确认要遍历QuerySet会花费很多时间。

也许有些东西在Django 2.2中是我不习惯的?我以前使用的是1.11,但以为我现在使用的是较新的版本。

我要迭代的模型:

+

并且,正如我提到的,该表中大约有28万行。

当我做一些简单的事情时,

class SupplierSkus(models.Model):
    sku = models.CharField(max_length=20)
    link = models.CharField(max_length=4096)
    price = models.FloatField()
    last_updated = models.DateTimeField("Date Updated", null=True, auto_now=True)
    status = models.ForeignKey(Status, on_delete=models.PROTECT, default=1)
    category = models.CharField(max_length=1024)
    family = models.CharField(max_length=20)
    family_desc = models.TextField(null=True)
    family_name = models.CharField(max_length=250)
    product_name = models.CharField(max_length=250)
    was_price = models.FloatField(null=True)
    vat_rate = models.FloatField(null=True)
    lead_from = models.IntegerField(null=True)
    lead_to = models.IntegerField(null=True)
    deliv_cost = models.FloatField(null=True)
    prod_desc = models.TextField(null=True)
    attributes = models.TextField(null=True)
    brand = models.TextField(null=True)
    mpn = models.CharField(max_length=50, null=True)
    ean = models.CharField(max_length=15, null=True)
    supplier = models.ForeignKey(Suppliers, on_delete=models.PROTECT)

该过程将很快消耗掉大多数CPU的能量,并且无法完成。同样,我无法对其进行迭代:

from products.models import SupplierSkus
sku_list = SupplierSkus.objects.all()
len(sku_list)

也只需要几个小时,就不会打印一行。但是,我可以使用以下命令对其进行迭代:

for i in sku_list:
    print(i.sku)

那对我没有太大帮助,因为我仍然需要通过Haystack进行索引编制,而且我相信这些问题是相关的。

与我合作过的某些早期项目不是这种情况。甚至相当大的列表(3-5m行)也将很快迭代。查询列表长度将花费一些时间,但返回结果的时间将是几秒钟而不是几小时。

所以,我想知道这是怎么回事? 这是别人遇到的吗?

1 个答案:

答案 0 :(得分:0)

好的,我发现问题出在Python MySQL驱动程序上。如果不使用.iterator()方法,则for循环将卡在QuerySet的最后一个元素上。我在an expanded question here上发布了更详细的答案。

  

我没有使用Django建议的mysqlclient。我正在使用   一个由Oracle / MySQL创建。似乎有一个错误会导致   用于在for中的QuerySet的最后一个元素上“卡住”的迭代器   循环并在某些情况下陷入无限循环。

考虑一下,很可能这是MySQL驱动程序的设计功能。我记得以前有与此驱动程序的Java版本类似的问题。也许我应该放弃MySQL并转向PostgreSQL?

无论如何,我都会尝试在Oracle中引起一个错误。