我看到很多像这样的答案:
Printing a list of persons with more than one home each home with more than one
我尝试过类似模型的答案,这似乎是一种非常低效的方法。每次迭代似乎都会进行单独的查询,有时会导致对数据库的数千次查询。我意识到你可以缓存查询集,但它似乎仍然是非常错误的。所以问题是,你使用那种方法吗?如果没有,你是怎么做到的?
答案 0 :(得分:6)
这是一个非常好的问题,不仅限于Django的ORM框架。
我始终认为记住对象关系映射(ORM)框架解决的一些问题非常重要:
面向对象的CRUD :如果应用程序的其余部分基于强大的面向对象原则,则使用对象访问数据持久性会使代码更加连贯,内部一致,有时候更短。
持久层封装:ORM在应用程序中为数据库访问提供了一个清晰的层。它封装了在一个位置读取/写入数据所需的所有功能,即所谓的DRY(不要重复自己)原则的缩影。这使得一些事情变得更加容易:模型更改,因为所有面向数据库的选择和插入/更新代码都在一个位置而不是整个应用程序 security ,因为所有数据库访问都通过一个位置和测试,因为如果它们被清楚地描绘出来,很容易模拟您的数据模型和访问。
SQL安全性:虽然很容易保护原始SQL使用以防止注入攻击等,但如果您将ORM框架作为单点数据库联系人来实现它,则会更容易对你而言,你永远不必考虑它。
请注意,速度不在列表中。 ORM是代码和数据库之间的间接级别。我们当然要求ORM设计人员负责编写能够生成良好SQL语句的框架,但ORM旨在提供代码和体系结构级别的效率,而不是执行效率。读过SQL基础书的开发人员将始终能够更好地与DB直接交谈。
肯定有策略可以解决这个问题,在Django中,正如ozan所提到的那样select_related()
,以及站点/视图/杂项缓存,但它们不会给你与直接SQL语句相同的性能。因此,在我需要速度的时候,我永远不会使用ORM框架,它不提供一些机制来发出原始SQL语句。例如,在从连接许多表的数据库中生成大型报表时,我经常使用原始SQL; ORM方式可能需要几分钟,SQL方式可能需要几秒钟。
话虽如此,我从不开始担心每个人的查询。我对任何进入ORM层的人的建议是:不要保护ORM的数据库访问权限。编写应用程序或模块,然后对其进行概要分析,调整那些真正需要性能提升的区域,或者使用缓存/ select_related来减少应用程序的整体DB-chattiness。
答案 1 :(得分:4)
您可以使用select_related() queryset method来减少数据库查询的数量。您还可以指定深度,因此在给定示例中,如果电话号码模型具有其他外来关系,则您将使用select_related(depth = 2)来避免选择相关实体的更多“级别”。