简介
如果你的应用程序变慢了,很有可能问题与你的数据库有关——至少部分有关。
知道你的应用程序的性能问题可能涉及你的数据库是减少延迟的好第一步。棘手的部分是找出在哪里以及为什么这些瓶颈可能存在。
本文介绍了一些导致数据库性能瓶颈的最常见问题,以及一些可以采取的解决措施。
数据库日志和指标
如果不查看日志,就不可能诊断数据库中的瓶颈。大多数云提供商会提供丰富的信息供你评估你的查询发生了什么,但可能很难知道这些信息在说什么。
探索日志、指标和查询统计信息
大多数云数据库提供商,包括 DigitalOcean、AWS、Google Cloud Platform、MongoDB Atlas 等,都提供了一个查看日志的地方。了解此日志信息的设计和结构很重要,这样你才能更轻松地找到以后的问题。
例如,DigitalOcean 提供了一个名为“日志和查询”的选项卡,可以直接从部署管理菜单访问。
在本节中,有一个名为“最近日志”的小节,它提供日志信息的实时显示。
这些日志中包含的信息可能对你要排除故障的特定瓶颈问题有用,也可能没有用。但是,一些信息(例如会话持续时间)可能表明某些会话花费了很长时间连接到数据库。
探索指标面板
云数据库提供商的指标面板可以让你深入了解你可能遇到的瓶颈。大多数云提供商会显示与性能相关的的信息,例如
- 系统和进程 CPU 使用率
- 缓存使用率
- 内存
- 连接数
查看系统 CPU 使用率等项目的指标可能会揭示与资源限制相关的问题。你可能会看到与执行备份等管理任务相关的使用率峰值。持续的高使用率可能表明你的数据库服务器配置不足。
探索查询统计信息
云数据库提供商的查询统计信息报告可能是确定减速原因的最佳信息来源。在许多情况下,减速可以追溯到执行时间很长的查询。
查询统计信息在不同提供商之间以不同的方式报告,但在大多数情况下,提供商都有一种方法可以显示被认为很慢的查询。大多数提供商会显示查询语句、它被调用的次数以及该特定查询的计时。
例如,DigitalOcean 的查询统计信息以表格格式显示此信息。
未索引的表
数据库表的索引在概念上类似于书中的索引。如果没有书的索引,你就只能翻阅每一页才能找到你感兴趣的主题。相反,如果这本书有索引,你就可以先在索引中搜索特定主题,然后它会指引你到正确的页面或页面。这大大减少了查找所需信息所需的时间。
数据库索引也采用了相同的概念。在数据库表中添加索引可以实现快速查找。
如果你从表中的一小部分数据开始,通常不会立即注意到与索引相关的问题。但是,随着数据的增长,缺乏索引会变得更加明显。
为你的表创建索引
数据库表的索引需要根据常见的访问模式创建。创建索引时,你要指定要为其构建索引的列或字段。
例如,如果你的表在 users
表中有一个 email
字段,你的应用程序中可能有一个基于电子邮件搜索用户的查询。如果没有索引,查询将搜索整个表以找到正确的记录。相反,如果你在 email
字段上创建一个索引,查询将首先查询索引以查找电子邮件值。找到后,它将指向该用户的特定数据库行。
确定添加索引机会的最佳方法是查看哪些查询执行时间很长。此信息可以在云提供商的数据库仪表盘的“查询统计信息”(或类似)部分找到。
在其他条件相同的情况下,最好首先关注报告中最慢的查询,为正在使用的访问模式添加索引。然后您可以向下移动列表,在需要时添加索引,直到解决慢速查询。
可以使用原始的 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
子句以减少返回的总数据量。 - 只选择所需的字段 - 在很多情况下,并非来自表的全部字段都适用于您的应用程序。只选择您的应用程序所需的特定字段,以防止过度获取。
- 审计您的架构 - 检查您的数据库 架构 以寻找减少复杂性的机会。依赖于许多连接的查询通常运行缓慢,可以通过调整架构以减少关系来改进。
- 使用数据库视图 - 视图类似于表,但是在预先运行查询以预先计算可能以动态方式派生的值的。视图有其自身的注意事项,并不适用于所有应用程序和用例。
结论
应用程序性能不佳通常可以追溯到数据库中的问题。通常,这些问题与次优查询有关。
优化查询没有万能的药方。但是,认真努力分析和检查某些查询执行不佳的位置和原因有助于确定应该调整的特定查询。一旦确定,对查询进行调整,例如添加索引、使用 WHERE
子句进行范围限定以及选择所需字段,可以产生更好的性能。
如果您使用的是 Prisma,您可以在我们的 性能和优化文档 中了解如何衡量和优化查询。