大牛/n-plus-one-detector

用于检测由 doctrine orm 触发的 n+1 查询的工具

dev-master 2020-08-11 08:52 UTC

This package is auto-updated.

Last update: 2024-09-11 17:48:56 UTC


README

动机

当你与 ORM 一起工作时,你需要处理 n+1 查询问题。如果你不熟悉它,你可以在这里了解更多关于它的信息 here。简而言之,这就是 ORM 由于你的代码以懒加载方式访问实体而导致 n+1 查询。

对于 n+1 的修复相当简单,它包括预先加载导致 n+1 的关系(无论是通过获取连接它们,还是对 doctrine 来说更好的是使用 部分脱水)。这些临时修复位于应用程序中获取特定用例根实体的部分。预先加载什么不能在加载时静态定义,因为它实际上取决于以后如何使用获取的实体。

尽管大多数开发者都很好地理解了 n+1 问题,但由于问题的性质,在执行某些应用程序更改时很容易忽略 n+1。考虑一下人们在使用模板引擎中的实体时的情况,他们只是满足了一个新的需求,显示更多一些信息,触发了新的 n+1。或者考虑一下将中心实体重构以替换标量属性与 x-to-one 关系的情况,因此你需要仔细分析重构方法的每个使用情况,以查看是否需要 n+1 修复。这就是 doctrine n+1 detector 发挥作用的地方。一旦启用,它将监听一些 doctrine 事件,检测由 doctrine 触发的 n+1 查询,并最终记录它们,以便用户可以在以后检查它们(或者如果他更喜欢,也许可以围绕这些记录创建警报)。换句话说,你仍然需要预先加载以避免 n+1 查询,但如果在生产中意外地出现 n+1,你有一个工具来让你意识到这一点,以便你可以尽早修复它们。

安装

你可以使用 composer 安装此包

composer require danydev/n-plus-one-detector

用法

你需要初始化检测器并调用 start,以便尽快开始检测 n+1,然后在请求生命周期中稍后可以检查所有检测到的 n+1。

// Start the n+1 detector at the start of our request handler.
$nPlusOneDetector = new NPlusOneDetector($entityManager);
$nPlusOneDetector->start();

//... normal request lifecycle happens here...

// Inspect n+1 detected just before returning the response
$result = $nPlusOneDetector->getDetectedNPlusOne();
foreach($result->getCollectionStats() as $stat) {
    error_log('[N+1-detected] on ' . $stat->getOwnerClass() . ' due to collection of ' . $stat->collectionElementsClass());
}
foreach($result->getProxyStats() as $stat) {
    error_log('[N+1-detected] on ' . $stat->getClass());
}

待办事项

  • PSR-15 中间件,用于启动和停止,可配置为可选的 PSR-3 日志记录器。
  • Symfony 包以集成到他们的 HttpKernel。
  • 检测由非拥有方一对一生成的 n+1(此 n+1 是 doctrine 中的设计,但用户可能会通知它很有价值)。
  • 检测由具有抽象父类的类中使用的 *-to-many 生成的 n+1(此 n+1 是 doctrine 中的设计,但用户可能会通知它很有价值)。
  • 编写一些测试。
  • 在 ci 上应用/执行 phpcs、psalm/phpstan。