随着应用程序(以及用于构建它们的工具)变得越来越复杂,并且数据需求变得越来越大,开发团队开发出能够在基线和规模上高效执行的应用程序至关重要。但是实现这个目标有很多障碍:像 N+1 问题这样的性能反模式可能会减慢或破坏最好的应用程序。
在本文中,我们将探讨 N+1 问题、Java 中 N+1 问题背后的常见原因。
Java 中的性能反模式
性能反模式通常围绕着在负载或规模上复合的低效或多余查询。出现这些模式的原因多种多样,但最终结果可能从性能差到级联故障。
我们今天看到的反模式称为 N+1 问题。它以对数据库的一系列过度请求为标志,并经常伴随对象关系映射 (ORM) 工具。
什么是 N+1 问题?
N+1 问题,也称为 N+1 选择问题或 N+1 查询,发生在服务从数据库请求多行 (N) 数据,然后单独请求这些项目的相关数据 N 次时。
在下面分布式 Spring PetClinic 演示应用程序的示例中,我们看到 vet.specialties 方法从数据库中请求 24 行,然后循环并通过单独的查询从数据库中请求 24 行。
那是 24 次调用,加上对数据库本身的 24 行数据的初始调用——或者,简而言之,N + 1 次调用。 当然,这些单独的行调用可以通过单个调用来完成。
是什么导致 Java 应用程序中的 N+1 问题?
有一些常见的罪魁祸首,它们通常与 ORM 工具或框架以及它们生成查询的方式有关。
1. ORM 框架
像 Java 这样的面向对象语言通常需要使用关系数据库。这要么意味着开发人员或数据库管理员需要编写(优化)SQL 请求,要么他们需要使用中间层,如 ORM 框架,为该数据库生成兼容的请求。虽然功能强大,但 ORM 框架在创建未优化查询(包括 N+1 查询)方面享有盛誉。
2. 延迟加载
默认情况下,像 Hibernate 这样的 ORM 框架可以在其生成的数据库请求中使用 FetchType.LAZY。而且,由于这些查询没有保持会话,因此每次请求服务需要时,都会对该数据库进行 N+1 次查询。
3. 开发人员和数据库管理员
事实是,这些 ORM 框架虽然很方便,但无法取代开发人员或数据库管理员自己编写请求的诚实努力。而且,由于 ORM 工具在开发人员没有太多监督的情况下生成查询(除了功能),因此开发人员在生产中出现之前不会看到这个问题。
发表评论 取消回复