本文字数:7780;估计阅读时间:20 分钟
作者:The ClickHouse & Goldsky teams
本文在公众号【ClickHouseInc】首发

简要概述:我们很高兴宣布 CryptoHouse 的推出,您可以通过 crypto.clickhouse.com 访问这一免费区块链分析服务,该服务由 ClickHouse 提供支持。
现有的公共区块链分析服务通常需要定期的异步查询,而 ClickHouse 则提供了实时分析,通过实现即时查询响应,降低了访问门槛。用户可以使用 SQL 查询这些由 Goldsky 实时更新的数据,并且完全免费。我们定制的用户界面支持保存和共享查询,并提供基本的图表绘制功能,还附有示例帮助用户快速入门。我们欢迎外部贡献示例查询,共同提升这项服务。
从今天起,CryptoHouse 用户可以免费查询 Solana 的区块、交易、token 转移、区块奖励、账户和 token 数据集。类似的数据集也适用于以太坊。我们计划在未来几个月内扩展数据范围,并支持更多区块链!
如果您对我们为何以及如何构建这一服务感兴趣,请继续阅读……
区块链分析的需求
区块链是复杂的系统,每秒可以处理数千笔交易和智能合约执行。了解其变化和状态对于投资者做出明智的决策,以及开发者构建这些合约至关重要。
SQL 是进行这些分析的理想语言,但这也带来了两个重大挑战:(1) 如何将区块链实体转换为结构化的、行导向的格式,以及 (2) 找到一个能够处理高吞吐量和潜在的数拍字节数据的数据库,同时满足用户的分析查询需求。
ClickHouse 是区块链分析的标准
作为一个开源的 OLAP 数据库,ClickHouse 以其列式设计和高度并行的执行引擎,非常适合用于存储区块链数据。这使得查询可以在数拍字节的数据上高效运行,提供对整个数据集的快速分析。因此,我们看到 ClickHouse 在区块链分析中得到了越来越广泛的应用,例如 Goldsky 和 Nansen 等公司将 ClickHouse 作为其产品的核心。
打造公共服务
关注 ClickHouse 并了解我们公开演示的人都知道,我们喜欢处理大型数据集,并围绕它们构建服务。今年早些时候,我们推出了 ClickPy,为 Python 包下载提供免费分析服务。最近,adsb.exposed 用惊艳的航班数据可视化效果震撼了社区。
我们早就意识到,区块链能够满足我们对大型复杂数据集的需求。在众多流行的区块链中,我们了解到 Solana 网络既具规模又非常复杂。尽管目前已有公共区块链分析服务,但用户通常需要安排查询,并等待其异步执行,结果则保存在稍后检索。作为 ClickHouse 的维护者,我们意识到可以通过更低的成本来提供实时区块链分析,从而更好地解决这个问题,并通过允许用户实时编写查询并获取响应,实现数据访问的民主化。
尽管我们在处理 ClickHouse 部分的工作上驾轻就熟,但坦白说,我们并不是加密领域的专家。将 Solana 区块链转换为结构化的行导向格式需要一些领域专业知识。因此,这个“挑战”一直处于暂停状态,直到今年早些时候我们有幸遇到了一些合作伙伴。
引入 Goldsky
Goldsky 是一个专注于加密货币数据基础设施的产品,为开发者提供工具,帮助他们使用 Solana 和其他区块链网络的数据构建高效的实时应用程序。Goldsky 的平台通过提供结构化格式的区块链事件实时数据流服务,将数据直接传送到数据库中,支持开发者构建可靠、数据驱动的 Web3 应用程序。
虽然 Goldsky 已经在其内部用例中广泛使用 ClickHouse,但他们的客户经常请求将区块链数据发送到他们自己的 ClickHouse 集群中进行分析。在去年末采访 Goldsky 的 CTO Jeff Ling 时,我们分享了关于构建 CryptoHouse 的想法。令我们惊喜的是,Jeff 非常愿意参与其中,并帮助解决我们在数据工程方面的问题!
数据工程挑战
Solana 每秒处理 3000-4000 笔交易,这些数据需要直接从节点中提取。最初,Goldsky 采用开源软件来支持 Solana,这等同于抓取内置的区块链节点 API。这种方法形成了一种架构,即新块被检测并加入队列,多个工作线程负责获取所需的所有交易,然后以最小延迟将这些交易传输到 Goldsky Mirror 数据流平台。
在实践中,每笔交易还被提取到其他数据集,如 token 转移和账户变更。数据摄取框架也进行了调整,以适应所有所需的下游转换。
随着数据开始实时流入平台,我们为所有需要支持的表创建了镜像管道配置。需要进行一些转换以确保数据与表匹配,这些表经过优化,以实现高效存储,并针对用户可能运行的常见查询。
# Example pipeline for blocks - this was repeated for all tables
name: clickhouse-partnership-solana
sources:
blocks:
dataset_name: solana.edge_blocks
type: dataset
version: 1.0.0
transforms:
blocks_transform:
sql: >
SELECT hash as block_hash, `timestamp` AS block_timestamp, height, leader, leader_reward, previous_block_hash, slot, transaction_count
FROM blocks
primary_key: block_timestamp, slot, block_hash
sinks:
solana_blocks_sink:
type: clickhouse
table: blocks
secret_name: CLICKHOUSE_PARTNERSHIP_SOLANA
from: blocks_transform
最后,由于最终的架构需要使用元组,在将数据集中的 JSON 转换为正确格式时遇到了一些困难。为了解决这个问题,我们利用 Null 表引擎结合物化视图,将 JSON 字符串转换为元组,执行 ClickHouse 特定的转换。例如,以下视图和 Null 表负责接收 tokens 数据集的插入,物化视图的结果则被发送到最终的 solana.tokens 表中:
CREATE TABLE solana.stage_tokens
(
`block_slot` Int64,
`block_hash` String,
`block_timestamp` DateTime64(6),
`tx_signature` String,
`retrieval_timestamp` DateTime64(6),
`is_nft` Bool,
`mint` String,
`update_authority` String,
`name` String,
`symbol` String,
`uri` String,
`seller_fee_basis_points` Decimal(38, 9),
`creators` String,
`primary_sale_happened` Bool,
`is_mutable` Bool
)
ENGINE = Null
CREATE MATERIALIZED VIEW solana.stage_tokens_mv TO solana.tokens
(
`block_slot` Int64,
`block_hash` String,
`block_timestamp` DateTime64(6),
`tx_signature` String,
`retrieval_timestamp` DateTime64(6),
`is_nft` Bool,
`mint` String,
`update_authority` String,
`name` String,
`symbol` String,
`uri` String,
`seller_fee_basis_points` Decimal(38, 9),
`creators` Array(Tuple(String, UInt8, Int64)),
`primary_sale_happened` Bool,
`is_mutable` Bool
)
AS SELECT block_slot, block_hash, block_timestamp, tx_signature, retrieval_timestamp, is_nft, mint, update_authority, name, symbol, uri, seller_fee_basis_points, arrayMap(x -> (x.1, (x.2) = 1, x.3), CAST(creators, 'Array(Tuple(String, Int8, Int64))')) AS creators,primary_sale_happened, is_mutable
FROM solana.stage_tokens
这种方法非常高效,并为我们提供了极大的灵活性,使我们能够以接近每秒 50 万行的速度进行数据回填。
在边缘,我们可以通过一个拥有 10 个工作线程的管道轻松优化所有边缘数据的处理,相当于每秒写入约 6000 行。
对于想了解增量物化视图在 ClickHouse 中工作原理的用户,我们推荐这些文档或这段视频。
在查询时,用户可能会注意到某些 Solana 区块和交易的时间戳为 1970-01-01,且高度为 0。虽然 Goldsky 提供了新数据,但 2024 年 6 月之前的数据行是从 BigQuery 回填的。这些数据的某些时间戳和高度值为空,在 ClickHouse 中,这些字段会转化为其相应类型的默认值——Date 和 Int64。我们计划在长期内修复这些数据质量问题。
ClickHouse 的挑战
确保公平使用
虽然 Solana 区块链的数据量对 ClickHouse 来说并不大,最大的表存储了约 500TiB 的交易(如下图所示),但我们希望提供一个功能,让任何人都能编写 SQL 查询。这为资源的公平管理带来了挑战,并需要确保单个查询不会耗尽所有的内存或 CPU 资源。
SELECT
`table`,
formatReadableSize(sum(data_compressed_bytes)) AS compressed_size,
formatReadableSize(sum(data_uncompressed_bytes)) AS uncompressed_size,
round(sum(data_uncompressed_bytes) / sum(data_compressed_bytes), 2) AS ratio
FROM system.parts
WHERE (database = 'solana') AND active
GROUP BY `table`
ORDER BY sum(data_compressed_bytes) DESC
┌─table─────────────────────────┬─compressed_size─┬─uncompressed_size─┬─ratio─┐
│ transactions │ 79.34 TiB │ 468.91 TiB │ 5.91 │
│ transactions_non_voting │ 17.89 TiB │ 162.20 TiB │ 9.07 │
│ token_transfers │ 3.08 TiB │ 18.84 TiB │ 6.11 │
│ block_rewards │ 1.31 TiB │ 10.85 TiB │ 8.28 │
│ accounts │ 47.82 GiB │ 217.88 GiB │ 4.56 │
│ blocks │ 41.17 GiB │ 82.64 GiB │ 2.01 │
│ tokens │ 3.42 GiB │ 10.10 GiB │ 2.96 │
└───────────────────────────────┴─────────────────┴───────────────────┴───────┘
10 rows in set. Elapsed: 0.009 sec. Processed 1.42 thousand rows, 78.31 KB (158.79 thousand rows/s., 8.74 MB/s.)
Peak memory usage: 99.91 KiB.
为确保公平使用(并控制可预测的成本),我们对 ClickHouse 使用配额,限制每个用户的查询最多可扫描 100 亿行数据。查询还必须在 60 秒内完成(大多数情况下,这得益于 ClickHouse 的性能),并且每个用户每小时最多可以运行 60 个查询。其他关于内存使用的限制旨在确保服务的稳定性和公平使用。
使用物化视图加速查询
有些查询不可避免地比其他查询更耗费计算资源。区块链查询通常需要扫描大量数据,对数百亿行数据进行摘要统计。为支持这类查询,我们提供了 ClickHouse 物化视图,将计算从查询时间转移到插入时间。这可以显著加速某些查询,并让用户能够获取整个数据集的统计结果。这些视图在数据插入时实时增量更新。举例来说,考虑以下查询,该查询计算上个月每天的费用:
SELECT
toStartOfDay(block_timestamp) as day,
avg(fee / 1e9) AS avg_fee_sol,
sum(fee / 1e9) as fee_sol
FROM
solana.transactions_non_voting
WHERE block_timestamp > today() - INTERVAL 1 MONTH
GROUP BY
1
ORDER BY 1 DESC
31 rows in set. Elapsed: 1.783 sec. Processed 2.12 billion rows, 50.98 GB (1.19 billion rows/s., 28.58 GB/s.)
Peak memory usage: 454.44 MiB.
该查询扫描了大约 20 亿行数据,耗时 2 秒。用户可以通过利用物化视图的示例查询获得相同结果:
SELECT day,
avgMerge(avg_fee_sol) AS avg,
sumMerge(fee_sol) AS fee_sol
FROM solana.daily_fees_by_day
WHERE day > today() - INTERVAL 1 MONTH
GROUP BY day
ORDER BY day DESC
31 rows in set. Elapsed: 0.007 sec. Processed 1.38 thousand rows, 60.54 KB (184.41 thousand rows/s., 8.11 MB/s.)
Peak memory usage: 4.88 MiB.
该查询仅耗时 0.007 秒。请注意,该视图按天聚合,因此对于需要更细粒度统计信息的查询,例如按小时查询某个特定日期的数据,我们建议使用源表 solana.transactions_non_voting。
当前的视图是与 Solana 基金会合作开发的,并在测试过程中进行了优化。如果用户发现某个查询触及配额限制,并且认为社区可以从中受益,只需在项目存储库中提交问题即可。我们可以创建视图并按需回填数据。未来,我们希望自动化这一过程,并公开一个构建系统,使用户可以简单地将视图提案或示例查询作为 PR 提交。
数据去重
为了高效地传递事件,Goldsky 采用了“至少一次”的消息传递语义。这意味着,尽管我们能够保证接收到链上发生的所有数据,但在极少数情况下,我们可能会多次接收到同一事件。为了解决这个问题,我们的表采用了 ReplacingMergeTree 引擎。
这种引擎会对具有相同表排序键(通常是 block_timestamp 和 slot)的事件进行去重。这个去重过程在后台异步进行,并最终达到一致性。如果插入了重复事件,结果可能会在一段时间内略有不准确,但由于行数巨大且重复率极低,我们预计这极少会成为问题,且大多数查询对行级别的精确性要求不高。有关 ReplacingMergeTree 工作原理的更多详细信息,请参见此处【https://clickhouse.com/docs/en/engines/table-engines/mergetree-family/replacingmergetree】。
使用 ClickHouse Cloud
该服务的实例托管在 ClickHouse Cloud 中,这带来了多个好处,尤其是存储与计算的分离。由于数据仅以单一副本存储在对象存储中,我们可以根据用户需求独立扩展 CPU 和内存。如果用户需求增加,我们只需添加更多节点,无需重新分片或重新分配数据。使用对象存储不仅简化了操作,还使我们能够实现有效的无限扩展,从而以更具成本效益的方式提供这项服务。
最后,我们利用了今年早些时候添加到开源版本中的 ClickHouse 查询缓存。
构建 UI
在解决了数据工程和 ClickHouse 的挑战之后,我们希望提供一个用户喜爱的服务,因此我们开发了一个简单的 UI,允许用户编写和共享查询。
我们了解到用户经常需要可视化查询结果,因此这个 UI 还支持由 e-charts 提供的简单多维图表功能。
请注意,用户可以将自己的查询保存在示例查询旁边。然而,这些查询不会在服务端保存,只会存在于浏览器的存储中。
查询提示
为了避免触及配额限制,我们建议用户:
-
使用物化视图。这些视图将计算任务转移到插入时,最大限度地减少用户查询所需读取的行数。
许多视图使用 AggregateFunction 类型,存储聚合的中间结果。
在查询时,需要使用 -Merge 函数来获取最终结果,如此处所示。
-
在主表上使用日期过滤器。物化视图按天聚合数据。
对于更细粒度的分析,请参考基表,例如 transactions。
这些表包含每个事件的数据,因此行数多达数百亿。
在查询这些数据时,务必应用日期过滤器,以避免超出一个月的时间跨度。
如果用户需要更多功能……
尽管我们已尽量提供宽松的配额,但我们预计一些用户可能需要运行超出 CryptoHouse 计算能力的查询。CryptoHouse 旨在供社区使用,不适合那些希望构建服务或商业产品的组织,因此不支持更大规模的查询需求。
如果您需要更高的配额或需要进行更多查询,建议联系 Goldsky,他们可以在专用的 ClickHouse 实例中为您提供数据。这些实例可以根据您的访问模式和需求进行优化,提供更优的性能和更低的查询延迟。
结论
我们很高兴宣布 CryptoHouse 现在已向用户和加密社区开放使用。这篇博客文章介绍了一些技术细节。
对于想了解更多细节的读者,我们将在 9 月的 Solana Breakpoint 大会上与 Goldsky 一起举办一场面向开发者的讲座,介绍这项服务的内部结构和我们遇到的挑战。
我们欢迎用户在公共存储库中提出问题和参与讨论。
征稿启示
面向社区长期正文,文章内容包括但不限于关于 ClickHouse 的技术研究、项目实践和创新做法等。建议行文风格干货输出&图文并茂。质量合格的文章将会发布在本公众号,优秀者也有机会推荐到 ClickHouse 官网。请将文章稿件的 WORD 版本发邮件至:[email protected]