- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我喜欢Django+DRF的组合,我已经用了很长时间,但这个问题困扰了我一段时间。问题是,当存在多个或多个关系和嵌套对象时,查询+序列化将花费大量时间。StackOverflow中有很多类似的问题,通常都是某种形式的N+1问题(或未解决)。
例如
Django REST Framework Serialize extremely slow
Badly affecting performance in populating ManyToMany field values in rest api (using django rest framework)
Django REST framework is slow
另外,建议不要一次加载那么多对象。。可能适用于这里,虽然我需要所有的项目一次。
How to optimize the django rest serializer with method field?
在本例中,处理查询也是问题的一个重要部分,但查询并不太多,查询本身也很快。我正在使用prefetch_related
来限制查询的数量和从DB查询中看到的内容一切看起来都很好..ish(?).I为每个prefetch_related
属性+序列化对象的原始查询获取一个查询。在prefetch_related
查询中有很多ID,但我想这是不可避免的,因为许多ID都是原始项目。
当这里所示的分析https://www.dabapps.com/blog/api-performance-profiling-django-rest-framework/时,我得到的结果是DB查找占用了大部分时间,而序列化也不太快。举个例子,我的本地PostgreSQL数据库中有一个“项目”的大约12k个“项”。所有“项目”都有1-5个“事件”,大多数“项目”也有1-2个“照片”。在我的笔记本电脑上获取和序列化这些数据大约需要22秒。我正在使用AWS EC2+RDS进行部署,那里的时间也差不多。在较大的“Item”集上,序列化时间的增长超过了DB查找时间,但是DB查找总是占用大部分时间。有了40k个条目,您将开始达到1分钟的执行时间,以及Nginx和堆栈其他部分的不同超时。
包含12k项的示例(下面是模型、序列化器和查询)
Database lookup | 14.0292s
Serialization | 6.0076s
Django request/response | 0.3488s
API view | 0.2170s
Response rendering | 1.1092s
Database lookup | 1.2447s
Serialization | 3.9668s
Django request/response | 0.2435s
API view | 0.1320s
Response rendering | 0.8495s
list
。因此,在序列化之前执行延迟查询。如果我不这样做,它不会改变整个结果,但是当用大约相同的时间序列化时,会计算数据库查找。
values()
。如果这样做了,还有办法利用DRF序列化器吗?我很喜欢他们。
class List(models.Model):
... CharFields, DateTimeFields, ForeignKeys etc. ...
class Item(models.Model):
list = models.ForeignKey(List, on_delete=models.CASCADE, db_index=True, null=True, related_name='items')
deleted_at = models.DateTimeField(db_index=True, blank=True, null=True, default=None)
created_by = models.ForeignKey(User, blank=False)
project = models.ForeignKey('projects.Project', on_delete=models.CASCADE)
... other CharFields, DateTimeFields, ForeignKeys etc. ...
class Event(models.Model):
item = models.ForeignKey(Item, on_delete=models.CASCADE, db_index=True, null=True, related_name='events')
created_by = models.ForeignKey(User, blank=False)
deleted_at = models.DateTimeField(db_index=True, blank=True, null=True, default=None)
... other CharFields, DateTimeFields, ForeignKeys etc. ...
class Photo(models.Model):
item = models.ForeignKey(Item, on_delete=models.CASCADE, db_index=True, null=True, related_name='photos')
created_by = models.ForeignKey(User, blank=False)
deleted_at = models.DateTimeField(db_index=True, blank=True, null=True, default=None)
... other CharFields, DateTimeFields, ForeignKeys etc. ...
class PhotoSerializer(serializers.ModelSerializer):
... other CharFields, DateTimeFields, ForeignKeys etc. ...
class EventSerializer(serializers.ModelSerializer):
createdBy = PrimaryKeyRelatedStringField(source='created_by', read_only=True)
createdByFullName = serializers.CharField(source='created_by.get_full_name', read_only=True)
... other CharFields, DateTimeFields, ForeignKeys etc. ...
class ItemSerializer(serializers.ModelSerializer):
listName = serializers.CharField(source='list.name', read_only=True)
createdBy = PrimaryKeyRelatedStringField(source='created_by', read_only=True)
createdByFullName = serializers.CharField(source='created_by.get_full_name', read_only=True)
photos = PhotoSerializer(many=True, read_only=True)
events = EventSerializer(many=True, required=False, allow_null=True, queryset=Event.objects.all())
... other fields ...
class ItemListAPIView(ListAPIView):
model = Item
serializer_class = ItemSerializer
def get_queryset(self):
return Item.objects.all().filter(project_id=...).filter(deleted_at__isnull=True).prefetch_related(
'created_by', # ID of user who created item
'photos', # Photo properties
'event__created_by', # Full name of the person who created the event
'list', # Name of the related list
)
django.db.backends: (0.196) SELECT "todo_item"."version", ... everything ... FROM "todo_item" WHERE ("todo_item"."project_id" = 1 AND "todo_item"."deleted_at" IS NULL) ORDER BY "todo_item"."created_at" DESC;
django.db.backends: (0.001) SELECT "auth_user"."id", ... everything ... FROM "auth_user" WHERE "auth_user"."id" IN (1, 2, ... some IDs ...);
django.db.backends: (0.148) SELECT "photos_photo"."version", ... everything ... FROM "photos_photo" WHERE ("photos_photo"."deleted_at" IS NULL AND "photos_photo"."item_id" IN (1, 2, ... lots of IDs... N)) ORDER BY "photos_photo"."created_at" DESC;
django.db.backends: (0.078) SELECT "events_event"."created_at", ... everything ... FROM "events_event" WHERE ("events_event"."deleted_at" IS NULL AND "events_event"."item_id" IN (1, 2, ... lots of IDs... N)) ORDER BY "events_event"."created_at" DESC, "events_event"."created_at" DESC;
django.db.backends: (0.157) SELECT "todo_list"."created_at", ... FROM "todo_list" WHERE "todo_list"."id" IN (1, 2, ... lots of IDs... N)
\timing
和
EXPLAIN ANALYZE
进行局部测试的。没有太详细的测量或调查,只是查询加起来不到1秒。与django.db.backends日志所建议的差不多。那些具有14秒DB查找时间的测试也在本地数据库中完成。套接字传输时间会影响,这是真的。物体很胖,但没有那么胖。总共有15个字段用于“Items”,而<10个字段用于“Events”和“Photos”。这会生成大量数据,但仍会生成足够的数据,以便在本地传输超过10秒,这听起来不太正确。不过,我可能错了。我会做更多的测试。谢谢你的回答!
time psql -f fat-query.psql --host=rds_host --port=5432 --username=user --dbname=dbname > output.txt
最佳答案
看来这不会像我希望的那样解决。由于仍然不知道与预取相关的Python JOIN为什么要花这么长时间,我用单独的queryset(尽管是相同的SQL查询)和适合这个用例的简单JOIN替换了prefetch_related
。
替换了GET“Items”中的Djangoprefetch_related
JOIN和DRF序列化:
不prefetch_related
,但单独的查询集会产生相同的SQL查询
使用values
,因为这次不需要对象
创建散列表,将“Item”ID作为通过单独查询获取的相关项的键
通过一次循环“items”将相关项连接到输出
在通过map循环“Items”的同时,还要使用字段名来匹配API规范
虽然正常的DRF序列化需要1分钟多一点的时间来序列化,例如50k个“项目”,但是用上面的6个步骤生成相同的输出大约需要10秒。
如果有人有足够的Django经验来指出Python中“default”prefetch+JOIN的行为为何如此糟糕,请告诉我。我知道使用prefetch_related
会让事情更快地发生,但是花1分钟加入5万个项目是错误的。目前,我假设Django正在连接时克隆queryset,生成一些有趣的循环或查询,这些循环或查询没有显示在Django.db日志中。不知何故,我的数据并不符合Django所考虑的“最佳”用例。
我在谷歌群组中也问了同样的问题:https://groups.google.com/forum/#!topic/django-users/je2LmRRjI_I
关于python - Django + Django REST Framework + PostgreSQL查询和序列化非常慢-并非“N + 1”情况,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44461638/
我是 python 的新手。我试图找到我的文本的频率分布。这是代码, import nltk nltk.download() import os os.getcwd() text_file=open(
我对安卓 fragment 感到困惑。我知道内存 fragment 但无法理解什么是 android fragment 问题。虽然我发现很多定义,比如 Android fragmentation re
尝试对 WordPress 进行 dockerise 我发现了这个场景: 2个数据卷容器,一个用于数据库(bbdd),另一个用于wordpress文件(wordpress): sudo docker
这个问题已经有答案了: From the server is there a way to know that my page is being loaded in an Iframe (1 个回答)
我正在玩小型服务器,试图对运行在其上的服务进行docker化。为简化起见,假设我必须主要处理:Wordpress和另一项服务。 在Docker集线器上有许多用于Wordpress的图像,但是它们似乎都
我想要发生的是,当帐户成功创建后,提交的表单应该消失,并且应该出现一条消息(取决于注册的状态)。 如果成功,他们应该会看到一个简单的“谢谢。请检查您的电子邮件。” 如果不是,那么他们应该会看到一条适当
就是这样,我需要为客户添加一个唯一标识符。通过 strip 元数据。这就是我现在完全构建它的方式,但是我只有最后一部分告诉我用户购买了哪个包。 我试着看这里: Plans to stripe 代码在这
我有一个类将执行一些复杂的操作,涉及像这样的一些计算: public class ComplexAction { public void someAction(String parameter
这个问题已经有答案了: maven add a local classes directory to module's classpath (1 个回答) 已关闭10 年前。 我有一些不应更改的旧 E
我使用 fragment 已经有一段时间了,但我经常遇到一个让我烦恼的问题。 fragment 有时会相互吸引。现在,我设法为此隔离了一个用例,它是这样的: Add fragment A(也使用 ad
我的 html 中有一个 ol 列表,上面有行条纹。看起来行条纹是从数字后面开始的。有没有办法让行条纹从数字开始? 我已经包含了正在发生的事情的片段 h4:nth-child(even) {
如何仅使用 css 将附加图像 html 化? 如果用纯 css 做不到,那我怎么能至少用一个图像来做 最佳答案 这不是真正的问题,而是您希望我们为您编写代码。我建议您搜索“css breadcrum
以下是 Joshua 的 Effective Java 的摘录: If you do synchronize your class internally, you can use various te
在这里工作时,我们有一个框向业务合作伙伴提供 XML 提要。对我们的提要的请求是通过指定查询字符串参数和值来定制的。其中一些参数是必需的,但很多不是。 例如,我们要求所有请求都指定一个 GUID 来标
我有 3 个缓冲区,其中包含在 32 位处理器上运行的 R、G、B 位数据。 我需要按以下方式组合三个字节: R[0] = 0b r1r2r3r4r5r6r7r8 G[0] = 0b g1g2g3g4
我最近发现了关于如何使用 History.js、jQuery 和 ScrollTo 通过 HTML5 History API 对网站进行 Ajax 化的要点:https://github.com/br
我们有一个 Spring Boot 应用程序,由于集成需要,它变得越来越复杂——比如在你这样做之后发送一封电子邮件,或者在你之后广播一条 jms 消息等等。在寻找一些更高级别的抽象时,我遇到了 apa
我正在尝试首次实施Google Pay。我面临如何指定gateway和gatewayMarchantId的挑战。 我所拥有的是google console帐户,不知道在哪里可以找到此信息。 priva
昨天下午 3 点左右,我为两个想要从一个 Azure 帐户转移到另一个帐户的网站设置了 awverify 记录。到当天结束时,Azure 仍然不允许我添加域,所以我赌了一把,将域和 www 子域重新指
我正在使用terms facet在elasticsearch服务器中获取顶级terms。现在,我的标签"indian-government"不被视为一个标签。将其视为"indian" "governm
我是一名优秀的程序员,十分优秀!