简介
如果您的应用程序速度变慢,很有可能问题至少部分与您的数据库有关。
了解您的应用程序性能问题可能涉及数据库是减少延迟的良好第一步。棘手的部分在于找出这些瓶颈可能存在于何处以及为何存在。
本文涵盖了在数据库中造成性能瓶颈的一些最常见问题,以及可以采取的一些补救措施。
数据库日志和指标
如果不查看日志,就无法诊断数据库中的瓶颈。大多数云提供商都提供丰富的信息,供您评估查询的运行情况,但可能很难理解这些信息在说什么。
探索日志、指标和查询统计
大多数云数据库提供商,包括 DigitalOcean、AWS、Google Cloud Platform、MongoDB Atlas 等,都提供查看日志的入口。熟悉这些日志信息的布局和结构非常重要,以便您日后能更轻松地发现问题。
例如,DigitalOcean 提供一个名为“日志与查询”(Logs & Queries)的标签页,可直接从部署管理菜单访问。
在此部分中,有一个名为“最近日志”(Recent Logs)的子部分,提供实时日志信息显示。
这些日志中包含的信息可能对您尝试解决的特定瓶颈问题有用,也可能没用。但是,某些信息(例如会话持续时间)可能会指示会话长时间连接到数据库的情况。
探索指标仪表板
您的云数据库提供商的指标仪表板能让您最深入地了解可能遇到的瓶颈。大多数云提供商会显示与性能相关的信息,例如:
- 系统和进程 CPU 使用率
- 缓存使用率
- 内存
- 连接数
查看系统 CPU 使用率等指标可能会发现与资源限制相关的问题。您可能会看到与执行备份等管理任务相关的用量峰值。持续的高用量可能表明您的数据库服务器资源不足。
探索查询统计
您的云数据库提供商的查询统计报告可能是确定性能瓶颈来源的最佳信息来源。在许多情况下,性能下降可以追溯到执行时间过长的查询。
不同提供商的查询统计报告方式不同,但在大多数情况下,提供商都有办法显示被认为是慢速的查询。大多数提供商会显示查询语句、其被调用的次数以及该特定查询的执行时间。
例如,DigitalOcean 的查询统计以表格形式显示此信息。
未索引的表
数据库表的索引在概念上类似于书中的索引。如果没有书中的索引,您将不得不翻阅每一页来查找您感兴趣的主题。如果书有索引,您可以先在索引中搜索特定主题,然后它会指向正确的页面。这大大减少了查找所需信息所需的时间。
同样的理念也适用于数据库索引。为数据库表添加索引可以实现快速查找。
如果您一开始表中只有少量数据,通常不会立即注意到与索引相关的问题。然而,随着数据量的增长,缺乏索引的问题会变得更加明显。
为您的表创建索引
数据库表的索引需要根据常见的访问模式创建。创建索引时,您需要指定索引应基于的列或字段。
例如,如果您的 users
表中有一个 email
字段,您的应用程序中可能有一个根据电子邮件搜索用户的查询。如果没有索引,查询将遍历整个表来查找正确的记录。相反,如果您在 email
字段上创建索引,查询将首先查询索引以查找电子邮件值。找到后,它将指向该用户的特定数据库行。
识别添加索引的最佳方法是查找哪些查询执行时间过长。此信息可以在您的云提供商数据库仪表板的“查询统计”(Query Statistics)部分(或类似部分)中找到。
在其他条件相同的情况下,最好首先通过为正在使用的访问模式添加索引来关注报告中最慢的查询。然后您可以依次处理列表,在需要的地方添加索引,直到慢速查询得到解决。
可以使用原始 SQL 创建索引。虽然具体细节因所使用的特定数据库而异,但创建索引的 SQL 命令可能如下所示:
CREATE INDEX email_index ON users (email);
索引到位后,请随着时间推移检查您的查询统计,以查看性能是否有所提升。
使用 EXPLAIN
检查慢查询
在某些情况下,您的云数据库提供商的查询统计仪表板可能无法为您提供足够的信息。它可能会显示哪些查询很慢,但可能不清楚应该创建哪些索引或应如何优化您的查询。
对于这些情况,您可以选择使用 EXPLAIN
语句检查您的查询。此语句与常规查询结合使用,有助于获取有关查询执行计划的详细信息。
例如,在 PostgreSQL 中在常规查询前使用 EXPLAIN
语句将生成以下信息:
- 估计启动成本
- 估计总成本
- 估计输出行数
- 行的平均宽度(字节)
例如,EXPLAIN
的以下用法:
EXPLAIN SELECT * FROM users;
将生成此报告
QUERY PLAN-------------------------------------------------------------Seq Scan on users (cost=0.00..458.00 rows=10000 width=244)
EXPLAIN
语句是深入研究特定查询并分析其成本的宝贵工具。使用 EXPLAIN
获取的信息超出了云提供商在查询统计报告中提供的信息,可用于优化您的查询。
大数据量
未优化的查询或范围过大的查询可能会从数据库返回异常大量的数据。当使用数据量极少的新数据库时,通常很难检测到此问题,但随着数据库大小的增长,这很可能会导致问题。
当查询返回大量数据时,需要将其扫描到数据库服务器的内存中。这可能导致 CPU 峰值和需要突发模式使用。这可能导致数据库服务器崩溃。如果数据从数据库服务器返回,如果您的应用服务器资源不足,它也可能对于应用服务器来说过大而无法处理。
解决数据过度获取问题需要优化查询,将选择范围限定在相关记录。解决方案通常是使用 WHERE
子句,但您首先需要找到导致问题的查询。
您的云数据库提供商的日志和指标可以提供一些迹象,表明数据库正在返回大量数据。您可能会看到突发信用额度使用或 CPU 峰值。然而,仅凭这些指标可能很难判断哪些查询是导致问题的原因。
在您的应用服务器中进行插桩
为了全面了解哪些查询导致返回大量数据,您可以在应用服务器中添加插桩。New Relic、Datadog 和 Dynatrace 等工具可以监控您的应用服务器,并报告数据通过时的大小。查找应用服务器的哪些端点或区域正在处理大量数据,可以帮助您确定哪些数据库查询可能是罪魁祸首。
查询优化
查询优化不是一劳永逸的事情,它很大程度上取决于具体情况。然而,有一些常见的优化类型值得考虑。
- 限制查询范围以防止过度获取 - 确保在适用时使用
WHERE
子句以减少返回的数据总量。 - 仅选择所需字段 - 在许多情况下,并非您表中的所有字段都为您的应用程序所必需。仅选择您的应用程序所需的特定字段以防止过度获取。
- 审计您的模式(Schema) - 检查您的数据库模式(Schema),寻找降低复杂性的机会。依赖大量连接的查询通常运行缓慢,可以通过调整您的模式(Schema)以减少关系来改进。
- 使用数据库视图 - 视图类似于表,但通过运行查询预先计算值而生成,这些值否则可能需要即时派生。视图有其自身的注意事项,并非适用于所有应用程序和用例。
结论
糟糕的应用程序性能通常可以追溯到数据库问题。很多时候,这些问题与次优查询有关。
查询优化没有万能药。然而,认真分析和检查某些查询为何表现不佳,有助于锁定需要调整的具体查询。一旦确定,对查询进行调整,例如添加索引、使用 WHERE
子句限定范围以及仅选择所需字段,可以显著提高性能。
如果您正在使用 Prisma,您可以在我们的性能和优化文档中了解如何衡量和优化查询。