Django QuerySet 与原始 SQL 性能考虑因素

Django QuerySet vs. raw SQL performance considerations

我正在学习 Django 及其 ORM 数据访问方法,有些事情我很好奇。在一个特定端点中,我进行了一些数据库调用(对 Postgres)——下面是其中一个示例:

projects = Project.objects\
            .filter(Q(first_appointment_scheduled=True) | (Q(active=True) & Q(phase=ProjectPhase.meet.value)))\
            .select_related('customer__first_name', 'customer__last_name',
                            'lead_designer__user__first_name', 'lead_designer__user__last_name')\
            .values('id')\
            .annotate(project=F('name'),
                      buyer=Concat(F('customer__first_name'), Value(' '), F('customer__last_name')),
                      designer=Concat(F('lead_designer__user__first_name'), Value(' '), F('lead_designer__user__last_name')),
                      created=F('created_at'),
                      meeting=F('first_appointment_date'))\
            .order_by('id')[:QUERY_SIZE]

如您所见,这不是一个小查询 - 我正在提取大量特定的相关数据并进行一些字符串操作。我比较关心性能,所以我尽我所能通过使用 select_related()values() 来提高效率,只得到我需要的东西。

我的问题是,从概念上和广义上讲,在什么时候使用参数化 SQL 而不是使用 ORM 来编写查询会变得更快(因为 ORM 必须首先 "translate"上面的"mess")?我应该切换到原始查询复杂度的大致水平 SQL?

任何见解都会有所帮助。谢谢!

The question I have is, conceptually and in broad terms, at what point does it become faster to just write my queries using parameterized SQL instead of using the ORM (since the ORM has to first "translate" the above "mess")?

如果你问的是性能,从不。

将 ORM 查询转换为 SQL 所花费的时间与实际执行该查询所花费的时间相比会非常少。脑细胞无可替代,服务器便宜

如果您确实有性能问题,首先要看的是模型中的索引。尝试打印出 ORM 生成的每个查询,并在你的 psql 控制台中通过前缀 EXPLAIN ANALYSE 运行 打印它们。

您也可以使用 django-debug-toolbar 来自动执行此操作。事实上,django-debug 工具栏是寻找瓶颈的重要工具。您会惊讶地发现您错过一个简单的 select_related 的频率以及这如何导致执行数百个额外的查询。

At what approximate level of query complexity should I switch over to raw SQL?

如果您问的是编码的难易程度,那要视情况而定。

如果查询很难使用 ORM 编写并且不可读,是的,那么使用原始查询就完全没问题了。例如,具有多个聚合的查询,使用常见的 table 表达式,多个连接等有时很难编写为 ORM 查询,在这种情况下,如果您使用原始 [=26= comfortable ] 这样写就可以了

同意@e4c5 所说的。

用于将 ORM 查询转换为原始 SQL 查询的附加转换层会影响性能。

但是,这种效果取决于您的查询的复杂程度?

当您使用 ORM 时,您可以通过增加应用程序中的处理来控制 DB 上的负载。此外,这还提供了在应用程序本身中缓存结果的机会。

最后,这完全取决于您的架构、查询的复杂程度以及您如何扩展数据库(索引、副本等)

阅读更多here