如何在 PHP 中检测 n+1 查询

未知
2024-05-11 12:58:01
0

#什么是n+1查询问题?

n+1查询问题是软件开发中常见的性能问题。 N+1 查询会导致许多不必要的数据库调用。这可能会导致您的应用程序以蜗牛般的速度运行,尤其是随着数据的增长。因此,您必须了解并解决 n+1 查询,以确保您的应用程序高效、响应灵敏且可扩展。

当应用程序进行一次数据库查询来检索一个对象时,就会发生 N+1 次查询,然后对于检索到的每个对象,它会进行其他查询来获取相关对象。这会导致对 N 个对象执行总共 N+1 次数据库查询,这会显着降低应用程序的效率和性能,尤其是在处理大型数据集时。

本文将探讨如何使用应用程序性能监控 (APM) 工具快速检测和解决 n+1 查询。

# N+1 查询图示:

让我们考虑一个需要显示作者及其书籍列表的书店应用程序。应用程序可能首先查询数据库以检索所有作者(1 个查询)。然后,对于检索到的每个作者,它会进行另一个查询来获取他们各自的书籍。如果有 100 位作者,则结果为 1(初始查询)+ 100(每位作者一个)= 总共 101 个查询。

这是非常低效的,并且会严重降低应用程序的性能。

为了避免 N+1 查询问题,开发人员经常使用诸如预先加载(在初始数据库查询本身中加载相关数据)或批量获取(其中批量检索多个对象的关联数据)等技术

#如何检测 n+1 个查询?

如果您有一个不平凡的应用程序,您可能有 n+1 个查询。如果您的应用程序是使用 Laravel 或 Symfony 等 Web 框架构建的,并使用 ORM,那么您肯定会有许多 n+1 查询。这是因为许多现代 Web 框架的 ORM 层默认延迟加载记录。

N+1 查询问题在您的开发和测试环境中可能会被忽视。尽管如此,当部署到生产环境时,它们可能会突然破坏应用程序的性能,因为数据库中的行数要高得多。

您的应用程序具有 n+1 个查询的明显迹象是正在执行的数据库查询数量异常高。

查询通常是连续的且不重叠的。

这一切都很好,但您可能想知道,“好吧,但我如何知道正在执行多少个查询以及它们是否是‘顺序且不重叠的?’”好问题!这就是应用程序性能监控 (APM) 工具的用武之地。

#使用 APM 工具查找 n+1 个查询:

顾名思义,应用程序性能监控工具是可用于监控和诊断应用程序问题的应用程序。此类工具可以帮助您监控各种性能指标,包括数据库查询。

有许多不同的 APM 工具可用。对于此示例,我将使用Scout APM

Scout APM 使查找 n+1 查询变得非常简单,因为它有一个专用的n+1 见解选项卡。 n+1 见解选项卡显示应用程序中所有端点的列表(以红色突出显示),对于每个端点,您可以查看运行了多少个查询以及它们花费了多长时间。单击单个端点将显示更深入的信息。

在端点详细信息页面上,您可以获得一个非常有用的时间线视图,您可以在其中看到 n+1 何时出现,例如,在部署更新后。上面的屏幕截图描述了精简视图,显示了对 n+1 查询所发生情况的简化见解。单击此处的 SQL 按钮(突出显示为蓝色),Scout 将向您显示值得指责的 SQL 查询。

#回溯

在端点详细信息页面上,您可以单击 Backtrace 按钮来查找负责 n+1 查询的确切代码行。

您可以在上图中看到,Scout 回溯到有问题的代码到导致问题的确切行。显示代码片段是因为我使用了Scout 的 GitHub 集成。但即使你没有 GitHub 集成,Scout 仍然会报告有问题的代码文件和行号。

现在我们知道如何使用 APM 查找 n+1 个查询,让我们继续解决它们。

#解决n+1个查询

为了说明如何使用 ORM(如 Laravel 的 Eloquent 或 Doctrine)解决 PHP 应用程序中的 N+1 查询问题,我们将根据前面提到的书店应用场景重新审视示例。

设想:

您有一个包含两个表的数据库:作者和书籍。每个作者可以有多本书。我们首先看一下导致 N+1 查询问题的代码,然后我将展示如何解决它。

具有 N+1 查询问题的代码:



// Retrieve all authors
$authors = Author::all();
 
foreach($authors as $author) {
   // For each author, retrieve their books$books = $author->books()->get(); // This causes an additional query for each author
   // Process the books...
}


在此代码中,第一个查询检索所有作者,然后,对于每个作者,执行一个新查询来获取他们的书籍,从而导致 n+1 个查询。

# N+1查询方案一:热切加载

解决 n+1 查询问题的一种方法是使用称为急切加载的策略。通过预先加载,您可以在初始查询中加载相关模型(在本例中为书籍)。



// Eager load books with authors in one query
$authors = Author::with('books')->get();
 
foreach($authors as $author) {
   // Now, no additional query is made here
   $books = $author->books;
   // Process the books...
}


# N+1查询方案二:Join查询

有时,您可能希望使用JOIN 语句来获取单个查询中的所有内容。您可以使用原始查询或框架提供的查询生成器来执行此操作。

原始查询示例(使用 PDO):


$sql = "SELECT * FROM authors JOIN books ON authors.id = books.author_id";
$stmt = $pdo->query($sql);
$authorsAndBooks = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Process the books accordingly


查询生成器示例(在 Laravel 中):



$authorsAndBooks = DB::table('authors')
   ->join('books', 'authors.id', '=', 'books.author_id')
   ->get();
 
// Process the results accordingly


使用原始查询或查询生成器允许您编写更优化的 SQL 查询,以在对数据库的单个请求中获取所需的数据。

# N+1查询方案3:缓存

解决 n+1 查询问题的另一种方法是使用缓存。缓存为 n+1 查询问题提供了一种战略解决方案,特别是当数据不经常更改时。通过将数据库查询的结果存储在缓存中,后续请求可以从该缓存中检索数据,而不用再次访问数据库。这显着减少了对数据库的查询数量,尤其是重复请求。

您应该注意,您可以将缓存与上述任一解决方案一起使用。

# PHP 中的 N+1 查询:结论

理解和处理 n+1 查询对于优化 PHP 应用程序至关重要。我们探讨了 n+1 查询是什么、它们如何默默地降低应用程序性能以及使用 Scout APM 等工具检测 n+1 问题的策略。

解决 n+1 查询不仅仅在于提高速度,还在于提高速度。这是关于编写更智能、更高效的代码。通过应用这些见解,您可以确保为用户提供更流畅、更快速的体验.

以上就是如何在 PHP 中检测 n+1 查询的详细内容,更多请关注全栈开发网其它相关文章!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 service@p2hp.com 进行投诉反馈,一经查实,立即处理!
-- -- 0

相关内容

如何使用 WinGet 在Windows上安装 PHP 8.4
如何使用 WinGet 在Windows上安装 PHP 8....
本文介绍了如何使用 winget 搜索、下载、安装、更新和删除 Windows PHP 二...
2025-02-20 11:28:50
高性能PHP框架 webman 开发规范1.0
高性能PHP框架 webman 开发规范1.0
总结下webman最新版本的开发规范以及代码建议。欢迎大家提交自己更好的开发规范以及代码建...
2025-02-20 11:00:49
现在你可以用一个命令安装 PHP 和 Laravel 安装程序
现在你可以用一个命令安装 PHP 和 Laravel 安装程...
创建第一个 Laravel 项目时,您需要确保先安装 PHP 和 Composer。但是,...
2024-10-17 15:32:51
Linux 6.9 内核正式版发布:支持 AMD P-State 首选核心、优化酷睿 Ultra 处理器性能
Linux 6.9 内核正式版发布:支持 AMD P-Sta...
Linux 6.9 内核正式版发布:支持 AMD P-State 首选核心、优化酷睿 Ul...
2024-05-14 10:42:43
Python 3.13 获首个 Beta 版更新:改进解释器 / 编译器性能、正式版有望 10 月发布
Python 3.13 获首个 Beta 版更新:改进解释器...
据 Python 博客,目前 Python 3.13 首个 Beta 版本已经发布,这是四...
2024-05-11 10:58:05
PHP老矣,尚能饭否? 近日 GitHut 最新公布的数据显示,开发者在 GitHub 提交的 PR 中,所使用语言为 PH...
为什么 Laravel 这么优秀 Laravel 一直是我心中最优雅的后端框架,为了向更多的人解释为什么 Laravel 这么优雅?框...
如何在 PHP 中检测 n+1 查询 n+1查询问题是软件开发中常见的性能问题。 N+1 查询会导致许多不必要的数据库调用。这可能会导致您...
现在你可以用一个命令安装 PHP 和 Laravel 安装程序 创建第一个 Laravel 项目时,您需要确保先安装 PHP 和 Composer。但是,如果您尚未...
我们都应该学习PHP PHP这三个字母官方的含义是这样的——PHP: Hypertext Preprocessor。但我想...
高性能PHP框架 webman 开发规范1.0 总结下webman最新版本的开发规范以及代码建议。欢迎大家提交自己更好的开发规范以及代码建议。
如何使用 WinGet 在Windows上安装 PHP 8.4 本文介绍了如何使用 winget 搜索、下载、安装、更新和删除 Windows PHP 二进制文件。...
PHP老矣,尚能饭否? 近日 GitHut 最新公布的数据显示,开发者在 GitHub 提交的 PR 中,所使用语言为 PH...
为什么 Laravel 这么优秀 Laravel 一直是我心中最优雅的后端框架,为了向更多的人解释为什么 Laravel 这么优雅?框...
如何在 PHP 中检测 n+1 查询 n+1查询问题是软件开发中常见的性能问题。 N+1 查询会导致许多不必要的数据库调用。这可能会导致您...

最新文章

如何使用 WinGet 在Windows上安装 PHP 8.4 本文介绍了如何使用 winget 搜索、下载、安装、更新和删除 Windows PHP 二进制文件。...
高性能PHP框架 webman 开发规范1.0 总结下webman最新版本的开发规范以及代码建议。欢迎大家提交自己更好的开发规范以及代码建议。
现在你可以用一个命令安装 PHP 和 Laravel 安装程序 创建第一个 Laravel 项目时,您需要确保先安装 PHP 和 Composer。但是,如果您尚未...
如何在 PHP 中检测 n+1 查询 n+1查询问题是软件开发中常见的性能问题。 N+1 查询会导致许多不必要的数据库调用。这可能会导致您...
为什么 Laravel 这么优秀 Laravel 一直是我心中最优雅的后端框架,为了向更多的人解释为什么 Laravel 这么优雅?框...
PHP老矣,尚能饭否? 近日 GitHut 最新公布的数据显示,开发者在 GitHub 提交的 PR 中,所使用语言为 PH...
我们都应该学习PHP PHP这三个字母官方的含义是这样的——PHP: Hypertext Preprocessor。但我想...