← 中文资源

简体中文版本

构建列式查询引擎

构建列式查询引擎:完整覆盖 analytical query processing,含 Column reader、Predicate pushdown 与测试的端到端实现。

阅读英文原文

项目概述

本项目实现一个面向 analytical query processing 的完整系统,核心要解决的问题是 scanning billions of rows for aggregates without deserializing irrelevant columns。整体由 Column reader、Predicate pushdown、Vectorized aggregate、Spill to disk、Query planner 五个模块组成,每个模块单一职责、可独立测试,最后通过集成测试验证端到端正确性。设计上把 a wide select that forces the engine to materialize many columns and exhausts the row-group cache 作为第一类需求先行处理,而非事后再补。

架构与关键决策

数据模型为 columns stored as typed, compressed arrays with min/max statistics per chunk to skip blocks during scans。Column reader 定义其余阶段共同依赖的数据形状并在边界处校验输入;Predicate pushdown 承载 analytical query processing 的正确性逻辑;Vectorized aggregate 专门处理 a wide select that forces the engine to materialize many columns and exhausts the row-group cache,在失败路径上给出明确的拒绝、重试或降级策略;Spill to disk 提供可观测性,每次操作输出带关联 id 的结构化事件;Query planner 在过载时按既定方式降级,避免过载演变为数据损坏。配置与代码分离,使风险变更可经 diff 审阅。

实施与测试

按五个阶段依次实现 Column reader、Predicate pushdown、Vectorized aggregate、Spill to disk、Query planner,每阶段配套聚焦单测。集成测试组合各模块并驱动真实 analytical query processing 场景:先验证正常路径,再刻意触发 a wide select that forces the engine to materialize many columns and exhausts the row-group cache 并断言系统降级而非损坏。所有依赖均在进程内或被桩替换,用例在 CI 中确定可复现。

限制与后续

  • 单区域设计,多区域复制超出范围。
  • Column reader 默认进程内,未水平共享。
  • 无鉴权层,假定部署在强制身份的边缘之后。

代码示例

# setup for columnar-query-engine
pnpm init
pnpm add apache-arrow duckdb-async
pnpm add -D typescript tsx vitest
columnar_query_engine/
├── src/index.ts
├── src/column-reader.ts
├── src/predicate-pushdown.ts
├── tests/columnar_query_engine.test.ts
└── package.json
// Column reader: analytical query processing core
export function columnreader(input: ColumnreaderInput): ColumnreaderResult {
  // Build the column reader that anchors analytical query processing and defines the core data shape.
  return processColumnreader(input);
}
// Predicate pushdown — handles analytical query processing Add the predicate pushdown so
export class Predicatepushdown {
  constructor(private opts: PredicatepushdownOptions) {}
  async run(ctx: Context): Promise<PredicatepushdownOutput> {
    return this.execute(ctx);
  }
}
// Vectorized aggregate: analytical query processing stage
export const vectorizedaggregate = (next: Next) => async (req: Request) => {
  const out = await transform(req);
  return next(out);
};
// Spill to disk for analytical query processing
export async function spilltodisk(stream: AsyncIterable<Chunk>): Promise<Aggregate> {
  let acc = init();
  for await (const c of stream) acc = merge(acc, c);
  return acc;
}
// Query planner: analytical query processing finalization
export function queryplanner(state: State): Result {
  validate(state);
  return finalize(state);
}
# run the analytical query processing test suite
pnpm vitest run