mcpField
C
clickhouse-js-node-rowbinary

clickhouse-js-node-rowbinary

github.com/clickhouse开发5626.4k 次安装1 周前更新
代码仓库

关于 clickhouse-js-node-rowbinary

面向使用 ClickHouse RowBinary 的 Node.js 开发者,指导生成 JavaScript/TypeScript 编解码器,将字节解码为值或将值编码为字节。技能涵盖格式选择、读写器实现原则及类型处理,并指出何时应考虑 JSON 或 Native 格式。

主要功能

  1. 01生成 RowBinary 读写器
  2. 02对比 JSON 与 Native 格式适用场景
  3. 03提供小端读写原则
  4. 04指导按类型生成专用代码
  5. 05涵盖流式与类型参考资料

适用场景

  1. 01解码 ClickHouse RowBinary 响应
  2. 02编码数据以发送至 ClickHouse
  3. 03为固定宽度数值列构建编解码器

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/clickhouse/agent-skills --skill clickhouse-js-node-rowbinary

安装后在 Claude Code 中输入/clickhouse-js-node-rowbinary确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

.gitignore
AGENTS.md
CHANGELOG.md
eval_result_composer.md
eval_result_haiku.md
eval_result_sonnet.md
eval_result.md
EXAMPLES.md
package-lock.json
package.json
reader.md
README.md
case-studies/
iot-rowbinary-vs-json.md
ledger-rowbinary-vs-json.md
logs-json-wins.md
wasm-vs-js.md
src/examples/
carts.ts
events.ts
iot.ts
ledger.ts
logs.ts
observability.ts
orders.ts
profiles.ts
telemetry.ts
src/readers/
aggregateFunction.ts
bool.ts
columnar.ts
compile.ts
composite.ts

详细介绍

适用于 Node.js 的 ClickHouse JS RowBinary 编解码器生成器

此技能可生成两种方向的线格式处理代码:读取器(解码字节 → 值)和写入器(编码值 → 字节,与读取器相反)。通常,一个任务只需要其中一种。此文件是共享入口——包含格式判断以及两种方向通用的原则;针对每种方向的决策、指南和各类型参考表分别位于两个同级文件中。

选择所需方向——只阅读对应文件:

  • 将 ClickHouse 返回的 RowBinary* 响应解码为 JS 值 → reader.md。涵盖流式处理与整缓冲区处理、行对象与列式处理、固定架构与运行时架构,以及各类型的读取器参考。
  • 将 JS 值编码为 RowBinary 负载并发送到 ClickHouse → writer.md。涵盖 Sink/writeX 基础构建块、writeRows 流式写入,以及各类型的写入器参考。

各类型的代码均可实际使用,并按方向分别存放在 src/readers/ 和 src/writers/ 中。

首先:RowBinary 真的是合适的格式吗?

RowBinary 的设计目标是高吞吐量,但它不一定总是最快的方式——在着手编写专用解析器之前,应先根据数据形态选择格式。

当结果主要是字符串或类似 JSON 的值,并且需要整体读取时,优先选择 JSON* 格式(例如 JSONEachRow)——比如需要随机访问几乎每个字段、对字段运行字符串或正则表达式方法,或将值视为文本。V8 原生的 JSON.parse 经过高度优化,使用 C++ 实现,构建 JS 字符串和对象的速度比 JS 层的 RowBinary 解码器更快;再配合 HTTP 响应压缩(gzip / zstd,可大幅压缩 JSON 中重复的键),也能降低网络传输开销。

当结果主要由以下内容组成时,RowBinary 明显更胜一筹:

  • 宽数值类型——Int128/Int256/UInt128/UInt256、 Decimal128/Decimal256。
  • 二进制/定长数据块——IPv4、IPv6、UUID、FixedString。
  • 通常而言,高容量定长数值列也适用,因为每个值只需一次 DataView 读取。

当主要目标是列式加载和客户端分析时,优先选择 Native 格式(对列进行折叠/扫描/筛选,并将类型化数组传给 Worker 或 WASM)。Native 按列存储,因此可将每列直接加载到一个类型化数组中,无需转置。

如果需要了解如何选择和使用 JSON* 格式(或 CSV / TSV),请使用 clickhouse-js-node-coding 技能。

核心指导原则(双向适用)

无论是生成读取器还是写入器,这些原则都适用;针对具体方向的操作指南见 reader.md / writer.md。

  • 仅使用小端序。 RowBinary 使用小端序;目标平台为 x86/ARM。读取和写入每个多字节数值时,都要使用 DataView 访问器,并为 littleEndian 标志传入字面值 true。

  • 先正确,再优化。 首先使用简单的逐类型 API 生成正确的编解码器。只有在编解码器正确且经过测试后,才进行专门优化。不要在确保正确之前就加入性能假设。

  • 对泛型/复合类型进行单态化。 针对每种类型组合生成专用内联代码,而不是在类型已知的情况下将函数作为参数传递。

  • 内联叶子操作。 每种类型的 readX/writeX 函数是正确且可组合的参考实现;生成的编解码器应内联其函数体,而不是调用它们,这样行循环就是直线代码,不会产生逐字段间接调用(也便于固定宽度合并操作整合偏移量计算)。

  • 为每列标注类型。 内联会抹去类型结构,因此应在每列的编码/解码代码块上方添加简短注释,注明所处理的 ClickHouse 类型。

  • 共享暂存区不可重入。 一些热点方法会复用模块级暂存缓冲区,按先写后读的顺序使用——只有访问完全同步时才正确。在写入和读取之间出现 async/yield 边界会破坏其中的值。

  • 默认使用 TypeScript。 除非用户明确要求纯 JavaScript,否则生成 TypeScript 代码和辅助代码。

示例

EXAMPLES.md 中收录了六个端到端示例,展示了实际的性能提升。

不在范围内

  • JSON / CSV / TSV / Parquet 解析 → 使用 clickhouse-js-node-coding。
  • 连接错误、挂起、类型不匹配 → 使用 clickhouse-js-node-troubleshooting。
  • 浏览器 / Web Worker / Edge → 使用 @clickhouse/client-web。

仍未解决?

评论

支持 Markdown