优化数据库性能

您可以通过几种不同的方法提升应用的 Firebase Realtime Database 性能。如需了解您可以采取哪些措施来优化 Realtime Database 性能,请通过不同的 Realtime Database 监控工具收集数据,然后相应地调整您的应用或您对 Realtime Database 的使用方式。

监控 Realtime Database 性能

您可以通过几种不同的工具收集有关 Realtime Database 性能的数据,具体取决于所需的细化程度:

  • 简要概览:使用性能分析器工具获取未编入索引的查询列表以及读/写操作的实时概览。
  • 计费用量的估算值:借助 Firebase 控制台中提供的用量指标,您可以了解计费用量和性能指标摘要信息。
  • 详细的深入分析:使用 Cloud Monitoring 可以更细致地了解您的数据库在一段时间内的表现。

根据指标提升性能

收集数据后,根据您要改进的性能领域,浏览以下最佳实践和策略。

性能改进策略概览
指标 说明 最佳实践
负载/利用率 优化在任意给定时间用于处理请求的数据库容量(反映在 **Load** 或 **io/database_load** 指标中)。 优化您的数据结构
将数据分片到多个数据库中
提升监听器效率
使用基于查询的规则来限制下载
优化连接
活跃连接数 平衡同时连到您的数据库的活跃连接数量,使其不超过连接数上限(20 万个)。 将数据分片到多个数据库中
减少新连接数
传出带宽 如果从您的数据库下载的数据量似乎高于预期,您可以提高读取操作的效率并减少加密开销。 优化连接
优化您的数据结构
使用基于查询的规则来限制下载
重复利用 SSL 会话
提升监听器效率
限制对数据的访问权限
存储 确保没有存储不使用的数据,平衡在其他数据库和/或 Firebase 产品中存储的数据量以免超过配额。 清理不使用的数据
优化您的数据结构
将数据分片到多个数据库中
使用 Cloud Storage for Firebase

优化连接

诸如 GETPUT 之类的 RESTful 请求仍然需要连接,虽然这种连接只是短期的。实际上,这些频繁的短期连接累积产生的连接费用、数据库负载和传出带宽可以显著高出数据库的实时活跃连接产生的响应各项。

因此,请尽可能使用与应用对应的平台相适应的原生 SDK,而不是 REST API。SDK 可使连接保持打开状态,从而减少因使用 REST API 而累积产生的 SSL 加密费用和数据库负载。

如果您确实需要使用 REST API,不妨考虑使用 HTTP keep-alive 以使连接保持打开状态,或使用服务器发送的事件,这样有助于降低 SSL 握手产生的费用。

将数据分片到多个数据库

将数据拆分到多个 Realtime Database 实例(也称为数据库分片)有以下三项好处:

  1. 通过将同时的活跃连接数分摊至多个数据库实例中,增加应用中允许的此类连接的总数。
  2. 在多个数据库实例之间均衡负载。
  3. 如果您有多个互不相关的用户组,且其需要访问的数据集也相互离散,请使用不同的数据库实例,以实现更高的吞吐量和更低的延迟。

如果您使用的是 Blaze 定价方案,则可以在同一个 Firebase 项目中创建多个数据库实例,并在多个数据库实例中使用一种通用的用户身份验证方法。

详细了解如何以及何时将数据分片

构建高效的数据结构

由于 Realtime Database 会检索所指定的路径及其子节点中的所有数据,因此最好使您的数据结构尽量扁平。 这样,您可以有选择地检索所需数据,避免将不必要的数据也下载到客户端。

具体来讲,请在设计数据结构时将写入和删除方面的问题纳入考量中。 例如,具有上千个子节点的路径可能会产生很高的删除费用。 如果将它们分摊至具有多个节点但每个节点的子节点较少的路径中,可以加快删除速度。

此外,每次写入在数据库总利用率中的占比可能会高达 0.1%。数据的结构应支持通过 SDK 中的 update() 方法或 RESTful PATCH 请求在一次操作中执行多次写入,以此实现多路径更新。

如需优化数据结构并提升性能,请遵循数据结构最佳做法

防止未经授权的访问

使用 Realtime Database Security Rules防止对数据库执行未经授权的操作。例如,使用规则可以避免恶意用户反复下载整个数据库的情况。

详细了解如何使用 Firebase Realtime Database 规则

使用基于查询的规则来限制下载

Realtime Database Security Rules 规则可限制对数据库中的数据进行访问,但它们也可用于限制访问通过读取操作返回的数据。使用基于查询的规则(例如由 query.limitToFirstquery. 表达式定义的规则)时,查询仅会检索由该规则限定的数据。

例如,以下规则规定只可读取查询的前 1000 个结果(按优先级排序):

messages: {
  ".read": "query.orderByKey &&
            query.limitToFirst <= 1000"
}

// Example query:
db.ref("messages").limitToFirst(1000)
                  .orderByKey("value")

详细了解 Realtime Database Security Rules

将查询编入索引

将数据编入索引可减少您的应用运行的每次查询所用的总带宽。

重复利用 SSL 会话

通过签发 TLS 会话票证来减少恢复连接时 SSL 加密开销所产生的费用。此方法特别适合需要频繁、安全地连接到数据库的情况。

提升监听器效率

将您的监听器部署在路径中尽可能深的地方,以限制它们同步的数据量。您的监听器应该靠近您希望其获取的数据。 请勿在数据库根目录下部署监听器,因为这会导致下载整个数据库。

添加查询以限制您的监听操作返回的数据,并使用仅下载数据更新的监听器。例如,使用 on() 而不是 once()。请将 .once() 用于真正不需要数据更新的操作。此外,尽可能使用 orderByKey() 对您的查询进行排序,以实现最佳性能。使用 orderByChild() 排序可能会使速度降低 6-8 倍;对于大数据集而言,使用 orderByValue() 排序可能会导致速度非常缓慢,因为它需要从持久层读取整个位置的数据。

此外,请务必动态地添加监听器,并在不再需要它们时将其移除。

清理不使用的数据

定期移除数据库中不使用的数据或重复数据。您可以执行备份来手动检查数据,也可以定期将数据备份到 Google Cloud Storage 存储桶。此外,您还可以考虑通过 Cloud Storage for Firebase 托管要存储的数据。

编写您可以更新且支持规模化扩展的代码

部署到物联网设备中的应用应采用您可以轻松更新且支持规模化扩展的代码。请务必对使用场景进行全面测试,考虑您的用户群可能会呈指数级增长的情形,并构建部署代码更新的功能。同时,请仔细考虑您将来可能需要做出的重大更改(例如,如果您决定将数据分片的话)。