We value your privacy

This site uses cookies to improve your browsing experience, analyze site traffic, and show personalized content. See our Privacy Policy.

  1. MooseStack
  2. Table Engines
  3. AggregatingMergeTree

AggregatingMergeTree

AggregatingMergeTree stores pre-aggregated values and/or aggregate states that are automatically merged during background compaction.

Use it with:

  • SimpleAggregateFunction for simple rollups (store merged values directly)
  • AggregateFunction for complex aggregations (store aggregate states and merge them at read time)
import {   OlapTable,   ClickHouseEngines,   SimpleAggregated,  Aggregated,  DateTime} from "@514labs/moose-lib"; interface DailyStats {  date: DateTime;  user_id: string;  // SimpleAggregateFunction(sum, UInt64)  total_views: number & SimpleAggregated<"sum", number>;  // SimpleAggregateFunction(max, Float64)  max_score: number & SimpleAggregated<"max", number>;  // SimpleAggregateFunction(anyLast, DateTime)  last_activity: DateTime & SimpleAggregated<"anyLast", DateTime>;} const dailyStats = new OlapTable<DailyStats>("daily_stats", {  engine: ClickHouseEngines.AggregatingMergeTree,  orderByFields: ["date", "user_id"]}); interface MetricsById {  id: string;  /**   * AggregateFunction(avg, Float64)   * Stores the result of avgState(rating) and is merged with avgMerge(...)   */  avg_rating: number & Aggregated<"avg", [number]>;  /**   * AggregateFunction(uniqExact, String)   * Stores the result of uniqExactState(user_id) and is merged with uniqExactMerge(...)   */  daily_uniques: number & Aggregated<"uniqExact", [string]>;} const metricsById = new OlapTable<MetricsById>("metrics_by_id", {  engine: ClickHouseEngines.AggregatingMergeTree,  orderByFields: ["id"],});

Supported Aggregate Functions

Review the ClickHouse aggregate functions documentation for the complete list of supported functions.

Example: Materialized View Rollup

Performance benefit

Pre-aggregating with AggregatingMergeTree can reduce query latency by orders of magnitude for dashboard queries, since aggregation happens at insert time rather than query time.

A common pattern is populating an AggregatingMergeTree table from a materialized view:

import {   OlapTable,   MaterializedView,  ClickHouseEngines,  UInt64,  SimpleAggregated,  DateTime,  sql} from "@514labs/moose-lib"; // Source: raw eventsinterface PageView {  timestamp: DateTime;  user_id: string;  page: string;  duration_ms: number;} const pageViews = new OlapTable<PageView>("page_views", {  orderByFields: ["timestamp", "user_id"],}); // Target: daily aggregatesinterface DailyPageStats {  date: DateTime;  user_id: string;  view_count: UInt64 & SimpleAggregated<"sum", UInt64>;  total_duration: number & SimpleAggregated<"sum", number>;  max_duration: number & SimpleAggregated<"max", number>;} const targetTable = new OlapTable<DailyPageStats>("daily_page_stats", {  engine: ClickHouseEngines.AggregatingMergeTree,  orderByFields: ["date", "user_id"],}); const mv = new MaterializedView<DailyPageStats>({  materializedViewName: "mv_daily_page_stats",  selectTables: [pageViews],  targetTable: targetTable,  selectStatement: sql`    SELECT      toStartOfDay(${pageViews.columns.timestamp}) AS date,      ${pageViews.columns.user_id}                AS user_id,      count()                                     AS view_count,      sum(${pageViews.columns.duration_ms})       AS total_duration,      max(${pageViews.columns.duration_ms})       AS max_duration    FROM ${pageViews}    GROUP BY date, user_id  `,});

See Also

  • Aggregate Types — SimpleAggregateFunction column types
  • Materialized Views — modeling AggregateFunction / aggregate states
  • Materialized Views — Populating aggregate tables
  • SummingMergeTree — Simpler option for sum-only aggregations

On this page

Supported Aggregate FunctionsExample: Materialized View RollupSee Also
FiveonefourFiveonefour
Fiveonefour Docs
MooseStackHostingTemplatesGuides
Release Notes
Source531
  • Overview
Build a New App
  • 5 Minute Quickstart
  • Browse Templates
  • Existing ClickHouse
Add to Existing App
  • Next.js
  • Fastify
Fundamentals
  • Moose Runtime
  • MooseDev MCP
  • Language Server
  • Data Modeling
Moose Modules
  • Moose OLAP
  • Moose Streaming
  • Moose Workflows
  • Moose APIs & Web Apps
Deployment & Lifecycle
  • Moose Dev
  • Moose Migrate
  • Moose Deploy
Reference
  • API Reference
  • Data Types
  • Table Engines
    • MergeTree
    • ReplacingMergeTree
    • AggregatingMergeTree
    • SummingMergeTree
    • Replicated Engines
  • CLI
  • Configuration
  • Observability Metrics
  • Help
  • Release Notes
Contribution
  • Documentation
  • Framework
import {   OlapTable,   ClickHouseEngines,   SimpleAggregated,  Aggregated,  DateTime} from "@514labs/moose-lib"; interface DailyStats {  date: DateTime;  user_id: string;  // SimpleAggregateFunction(sum, UInt64)  total_views: number & SimpleAggregated<"sum", number>;  // SimpleAggregateFunction(max, Float64)  max_score: number & SimpleAggregated<"max", number>;  // SimpleAggregateFunction(anyLast, DateTime)  last_activity: DateTime & SimpleAggregated<"anyLast", DateTime>;} const dailyStats = new OlapTable<DailyStats>("daily_stats", {  engine: ClickHouseEngines.AggregatingMergeTree,  orderByFields: ["date", "user_id"]}); interface MetricsById {  id: string;  /**   * AggregateFunction(avg, Float64)   * Stores the result of avgState(rating) and is merged with avgMerge(...)   */  avg_rating: number & Aggregated<"avg", [number]>;  /**   * AggregateFunction(uniqExact, String)   * Stores the result of uniqExactState(user_id) and is merged with uniqExactMerge(...)   */  daily_uniques: number & Aggregated<"uniqExact", [string]>;} const metricsById = new OlapTable<MetricsById>("metrics_by_id", {  engine: ClickHouseEngines.AggregatingMergeTree,  orderByFields: ["id"],});
import {   OlapTable,   MaterializedView,  ClickHouseEngines,  UInt64,  SimpleAggregated,  DateTime,  sql} from "@514labs/moose-lib"; // Source: raw eventsinterface PageView {  timestamp: DateTime;  user_id: string;  page: string;  duration_ms: number;} const pageViews = new OlapTable<PageView>("page_views", {  orderByFields: ["timestamp", "user_id"],}); // Target: daily aggregatesinterface DailyPageStats {  date: DateTime;  user_id: string;  view_count: UInt64 & SimpleAggregated<"sum", UInt64>;  total_duration: number & SimpleAggregated<"sum", number>;  max_duration: number & SimpleAggregated<"max", number>;} const targetTable = new OlapTable<DailyPageStats>("daily_page_stats", {  engine: ClickHouseEngines.AggregatingMergeTree,  orderByFields: ["date", "user_id"],}); const mv = new MaterializedView<DailyPageStats>({  materializedViewName: "mv_daily_page_stats",  selectTables: [pageViews],  targetTable: targetTable,  selectStatement: sql`    SELECT      toStartOfDay(${pageViews.columns.timestamp}) AS date,      ${pageViews.columns.user_id}                AS user_id,      count()                                     AS view_count,      sum(${pageViews.columns.duration_ms})       AS total_duration,      max(${pageViews.columns.duration_ms})       AS max_duration    FROM ${pageViews}    GROUP BY date, user_id  `,});