Django ORM在QuerySet上迭代的速度真的很慢



我正在做一个新项目,不得不非常快速地构建几页的大纲。

我导入了想要搜索的 280k 产品的目录。我选择了Whoosh和Haystack来提供搜索,因为我在以前的项目中使用了它们。 我添加了索引的定义并启动了该过程。然而,看起来 Django 迭代 QuerySet的速度非常非常慢。 最初,我认为索引花费了超过 24 小时 - 这似乎很荒谬,所以我测试了其他一些东西。我现在可以确认迭代查询集需要很多小时。

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

我正在尝试迭代的模型:

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)

而且,正如我提到的,该表中大约有 280k 行。

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

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

该过程将很快消耗大部分CPU功率并且不会完成。同样,我无法迭代它:

for i in sku_list:
print(i.sku)

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

for i in sku_list.iterator():
print(i.sku)

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

我之前参与过的一些项目并非如此。即使是一个更大的列表(3-5m行)也会很快迭代。查询列表长度需要一些时间,但返回结果的时间是几秒钟而不是几小时。

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

好的,我发现问题是Python MySQL驱动程序。如果不使用.iterator()方法,for循环将卡在 QuerySet 中的最后一个元素上。 我在这里发布了关于扩展问题的更详细的答案。

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

仔细想想,这很可能是MySQL驱动程序的设计功能。我记得以前使用此驱动程序的 Java 版本时遇到过类似的问题。也许我应该放弃MySQL并转向PostgreSQL?

无论如何,我都会尝试向甲骨文提出一个错误。

最新更新