上期推文列举了 RisingWave Grafana 看板上显示的一些重要指标,了解这些指标有助于诊断潜在问题。本文将为大家介绍 RisingWave 性能优化的最佳实践。
1何时创建索引
在 RisingWave 中,索引用于加速批量查询。关于索引相关的基础知识,请查看 Indexes[1]和 CREATE INDEX
[2]。
通过以下方式可以确定如何创建索引:
查看 Materialized Views(物化视图,MV)里的
SELECT
语句中使用了哪些列,这些列在创建索引时都应该出现在INCLUDE
子句中。在批量查询的可选
WHERE
条件中,哪些列包含在其中?假设批量查询使用名为timestamp
的列进行过滤,条件为timestamp between t1 and t2
,那么timestamp
列应该包含在index_column
中。该原则也适用于其他筛选条件,如等式和不等式。
需要注意的是,RisingWave 中索引的增量维护与 MV 的增量维护相似,但计算量较小。因此,在 RisingWave 中创建索引在成本上更具优势。我们鼓励用户检测批量查询中的模式,如果某个模式频繁出现或批量查询速度较慢,则考虑创建索引。
2何时在 MV 上构建 MV
在构建 MV 时,可以在现有的 MV 上构建更多的 MV。这种方法类似于在代码库中通过组合简单函数来创建复杂功能,并具有以下优势:
简化复杂查询,减少冗余,从而降低所需资源。典型用例是在不同时间维度上汇总某些指标,例如,跟踪每分钟、每小时和每天的订单数量。我们可以构建一个按分钟汇总的 MV,然后在其上构建一个按小时汇总的 MV,最后,在小时 MV 的基础上再添加一个按天汇总的 MV。
为用户访问常用数据提供一个稳定简单的数据接口,让用户不需要了解底层数据源的复杂细节和变更,比如第三方系统中数据模式的变更。
可能会有用户担心将复杂的流程拆分成多个 MV 会增加性能开销,但实际上,这些拆分并不会增加计算开销,只是会占用更多存储空间。由于 RisingWave 通常与公共云上价格低廉的对象存储一起部署,用于存储大量数据,因此在大多数情况下无需担心该问题。我们计划推出新功能,在 MV 对存储空间造成显著担忧时,允许移除不必要的中间 MV。
3何时纵向或横向扩展计算和压缩资源?
此讨论仅限于 Compute 节点和 Compactor 节点,因为在大多数情况下,其他组件不参与处理。
RisingWave 从一开始就是可扩展的分布式处理系统。然而,就像任何其他分布式系统一样,成为分布式系统会引入额外的开销,因为不同机器之间需要更多的网络通信。此外,随着更多机器拆分相同总资源,容易出现资源碎片化。不过这是分布式系统的固有特性,并非 RisingWave 本身的特殊限制。
因此,对于 Compute 节点,我们通常更倾向于纵向扩展(Scale up)而非横向扩展 (Scale out)。如果流式查询主要是无状态的(即没有 Aggregation、Join 或 Over window function),并且不涉及数据洗牌,那么纵向扩展和横向扩展的效果是相同的。
在 Compactor 节点方面,如果 Compactor 节点的资源少于 4 个 CPU 和 8 GB 内存,我们更倾向于进行纵向扩展,因为一些压缩任务偶尔可能会对资源产生较大需求,最多可使用 4 个 CPU 和 8 GB 内存。然而,一旦 Compactor 节点的资源超过此阈值,纵向扩展和横向扩展同样适用。
4何时创建 Source 或声明 append only 表?
在 RisingWave 中,当连接到外部上游系统时,我们可以声明 Source、表格和 append only
表。
Source 和其他两种类型的表区别在于,Source 不会将读取的数据持久保存在 RisingWave,而两种表会保存。数据存储在 RisingWave 后,用户可以在表格中插入、删除和更新数据,但对于 append only
表只能插入数据。因此,用户需要在占用更多存储空间和放弃在 RisingWave 中修改源数据的能力之间进行权衡。详细信息请参见 CREATE SOURCE
[3]。
另一个区别是性能影响。与表格不同,Source 和 append only
表永远不会处理任何更新或删除,使得性能有了优化的空间。
假设有一个 MV 跟踪零售银行所有客户中最大账户余额,例如,CREATE MATERIALIZED VIEW max_account_balance AS SELECT max(balance) FROM account_table
。由于每个客户的账户余额经常变动,我们不能将其声明为 Source 或 append only
表。RisingWave 必须持久保存所有账户的余额以维护结果,例如在最大余额减少时找到第二大余额是多少。
假设有另一个 MV 跟踪所有交易中的最新交易时间,即,CREATE MATERIALIZED VIEW time_latest_transaction AS SELECT max(timestamp) FROM transactions
。由于交易是不可逆的(即使某个交易出错,我们会通过新交易来纠正),我们可以将交易声明为 Source 或 append only
表。RisingWave 只需保留一个数据点,即最新交易的时间戳,并简单地将其与新交易的时间戳进行比较以更新结果。
在一些用例中,append-only
与 non-append-only
的区别可能会产生影响:
具有带有
ORDER BY
子句,并且只关注前 N 行的 Over-window 函数。去重。
Join。
这是一个仍处于试验阶段的高级功能,如有问题,请随时在社群中提出。
5总结
有关性能优化的任何其他问题,请关注我们的 RisingWave 中文开源社区公众号并加入社群,或加入 Slack 英文社区[4],与广大用户群体一同参与讨论、寻求帮助、分享经验,我们的工程师将提供相应的解决方案。
Indexes: https://docs.risingwave.com/docs/current/indexes/
[2]CREATE INDEX: https://zh-cn.risingwave.com/docs/current/sql-create-index/
[3]CREATE SOURCE: https://zh-cn.risingwave.com/docs/current/sql-create-source/
[4]Slack 英文社区: https://www.risingwave.com/slack
关于 RisingWave
往期推荐
技术内幕