使用 PostgreSQL 优化 Django 中的查询性能:案例研究
最近,我开始开发一项功能,这项功能需要我优化从我编写的代码中触发的数据库查询。这项优化对于确保主页快速加载、提供无延迟的无缝用户体验至关重要。
让我简单介绍一下我正在使用的应用程序。这是一个带有 **PostgreSQL** 数据库的 **Django** 应用程序。我正在开发的功能涉及需要来自多个模型的数据的逻辑,因为该应用程序模块化得很好。
**更加模块化?有问题!**
我们都倾向于遵循已学过的某些编码原则,其中之一就是编写模块化、可重复使用的代码。这种方法对于可维护性和可扩展性非常有用,但在数据库查询方面,有时会导致效率低下。
在 Django 中检查查询执行时间
首先,我想检查从我的代码中触发的查询的性能。我得到了原始 SQL,然后尝试在 **pgAdmin** 中执行它,并使用“EXPLAIN ANALYZE”分析结果。例如,如果您想分析查询,请在其前面加上“EXPLAIN ANALYZE”。
下面是我使用“IN”子句时的样子:
"Unique (cost=8.19..8.20 rows=1 width=16) (actual time=0.045..0.047 rows=1 loops=1)" " -> Sort (cost=8.19..8.20 rows=1 width=16) (actual time=0.045..0.045 rows=1 loops=1)" "Planning Time: 0.229 ms" "Execution Time: 0.076 ms"
接下来,我改用“JOIN”,结果如下:
"HashAggregate (cost=30.07..32.69 rows=262 width=16) (actual time=0.148..0.150 rows=1 loops=1)" " Batches: 1 Memory Usage: 37kB" " -> Nested Loop (cost=4.21..28.76 rows=262 width=16) (actual time=0.119..0.140 rows=1 loops=1)" "Planning Time: 0.455 ms" "Execution Time: 0.222 ms"
**注意到什么了吗?**
是的,**“执行时间”**!
它表明,对于这种特定情况,使用“IN”比使用“JOIN”更快。但是,我们需要考虑一个关键问题:这是否适用于更大的数据集?如果“IN”子句中的数据明显更大,会发生什么?它仍然表现良好吗?答案是**绝对不行**。
性能比较
为了更好地理解 `IN` 和 `JOIN` 之间的权衡,让我们分析一下数据库如何处理这两种方法,尤其是在数据集增长时。
**使用 IN**:
使用“IN”时,数据库本质上是在检查主表中的每一行是否存在于值列表中。虽然对于较小的数据集,这可能很快,但随着“IN”子句中的列表增长,PostgreSQL 必须扫描更大的值集。这会导致执行时间增加,并且可能导致全表扫描,尤其是在子查询或值列表很大的情况下。
**使用 JOIN**:
另一方面,`JOIN` 根据列中的匹配值在表之间建立关系,从而允许数据库使用索引优化流程。虽然对于小数据集,执行时间似乎更差(正如我们在初始测试中看到的那样),但在处理较大的数据集时,`JOIN` 的性能要好得多。
你可以使用什么?
视情况而定!是的,这取决于您的用例和您要解决的问题。您并不总是应该使用 `JOIN` — 对于较小的数据集,`IN` 可能更有效。
因此,请充分了解用例,并从比您更了解用例的人那里获取见解。如果您觉得数据会很大并且会影响性能,那么您绝对可以选择“JOIN”。是的,不要忘记在数据库上创建**索引**,以使您的“JOINS”性能更好。
更好地了解索引
在处理大型数据集的连接时,索引至关重要。索引允许 PostgreSQL 根据索引列快速定位行,从而显著提高查询性能。要优化“JOIN”查询,请确保“ON”子句中使用的列以及其他经常查询的列(如 WHERE 和 ORDER BY 子句中的列)。
想要了解有关 PostgreSQL 索引策略的更多信息?请查看有关选择表索引的资源。
我的决定
在评估了 `IN` 和 `JOIN` 方法后,我决定在数据预计会增长的情况下使用 `JOIN`,因为它在处理较大的数据集时能提供更好的性能。但是,在我知道数据量会保持较小的情况下,我选择了 `IN`,因为它可以为较小的数据集提供更快的查询执行速度。
此外,我还对关键列(如 id)实现了索引,以确保`JOIN`查询在应用程序扩展时继续表现良好。
总之,**始终评估您的使用情况,根据数据大小选择最合适的方法,并随时监控您的查询**,以确保在数据扩展时持续优化性能。
祝你编码愉快!💻