ChistaDATA · Database warehousing consulting, 24×7 support and managed services on ClickHouse
Database warehousing is the discipline of running an analytical warehouse as a production database: conformed dimensions, versioned history, marts built from declared dependencies, and freshness, cost and correctness measured per dataset. ChistaDATA delivers it on 100% open-source ClickHouse, in your own cloud account or data centre, as consulting, 24×7 consultative support and fully managed services under one escalation matrix.
This page describes the warehouse we build and operate at engineering depth: the raw, staging and mart layers and their table engines, how a star schema maps onto MergeTree, dictionaries and projections, the incidents a warehouse produces and the system tables that reveal them, the operating rhythm of a managed warehouse, and how legacy warehouses are migrated in.
On this page
- Why database warehousing on ClickHouse
- Database warehousing reference architecture
- Modelling for database warehousing: star schema on MergeTree
- Pipelines: dbt, incremental loads and restatements
- Database warehousing support: incidents and runbooks
- Managed database warehousing: the operating rhythm
- Migrating database warehousing from Redshift, Snowflake and BigQuery
- Security, governance and compliance
- Database warehousing engagement models and SLAs
- Database warehousing patterns by industry
- Database warehousing FAQ
Positioning
Why database warehousing on ClickHouse, and when a cloud warehouse is still the right call
A warehouse has two jobs that pull in opposite directions: absorb everything the business produces, and answer questions about it in the time a person is willing to wait. Cloud warehouses solved the first job with elastic storage and the second with elastic compute, priced per query or per credit. ClickHouse solves both with a columnar MergeTree engine that compresses aggressively, a sparse primary index that skips most of the data on every read, and vectorised execution across every core, at a fixed and predictable infrastructure cost. For workloads that are event-scale, latency-sensitive or served to many concurrent users, that is a different economic and operational proposition.
| Dimension | Cloud warehouse (Redshift, Snowflake, BigQuery) | Database warehousing on ClickHouse |
|---|---|---|
| Cost model | Per credit, slot or scanned byte; concurrency scales cost | Fixed compute and object storage; concurrency is a sizing decision |
| Latency | Seconds to tens of seconds on warm clusters; cold starts | Sub-second on sort-key-aligned queries; milliseconds on marts and projections |
| Freshness | Micro-batch, minutes at best on most tiers | Seconds through the Kafka engine or Connect sink |
| Concurrency | Queued per warehouse size; embedded analytics is expensive | Hundreds of concurrent readers per replica set; scale replicas for more |
| Ownership | Vendor-managed; data in a proprietary format | Your account, open source, open formats; ChistaDATA operates it if you choose |
| Where cloud database warehousing still wins | Large ad-hoc joins across unmodelled data by a small analyst team a few times a day, zero-ops requirements with no latency target, or an estate already standardised on it; ChistaDATA says so in the assessment when that is the case | |
Reference architecture
The database warehousing reference architecture ChistaDATA builds on ClickHouse
The warehouse is one ClickHouse estate. Its layers are databases and table engines rather than separate products: a raw landing layer that keeps data as delivered, a staging layer that types, conforms and versions it, and serving marts shaped by the dashboards that read them. Platform services (Keeper, tiered storage, backups, governance, observability and the access gateway) live inside the same estate and are covered by the same support plane.

Three design rules hold across every deployment. The raw layer is append-only and cheap: MergeTree partitioned by day, deduplicated by insert block only, aged to object storage by TTL and deleted after the replay window, so that any downstream table can be rebuilt from it. The staging layer is where correctness lives: ReplacingMergeTree with a monotonic version per source row, typed columns, conformed keys and SCD2 validity ranges, built by incremental models. The mart layer is where speed lives: fact tables whose sort keys come from the top dashboard fingerprints, dimensions held as dictionaries, and AggregatingMergeTree materialized views and projections for anything read more than once a minute.
Modelling
Database warehousing models on ClickHouse: how facts, dimensions and aggregates take physical form
Dimensional modelling survives the move to ClickHouse intact; what changes is the physical form each object takes. Small, slowly changing dimensions become dictionaries, so a join is an in-memory lookup rather than a hash join. Facts become wide MergeTree tables with a sort key derived from how they are filtered. History-dependent attributes keep a versioned copy for point-in-time joins. Aggregates that dashboards hit continuously are precomputed as mergeable states.

-- ClickHouse 25.x / 26.x LTS: database warehousing objects, fact table, dimension dictionary and aggregate mart
CREATE TABLE mart.fact_sales ON CLUSTER '{cluster}'
(
sale_id UInt64,
sale_date Date,
sale_time DateTime64(3, 'UTC') CODEC(DoubleDelta, ZSTD(3)),
region_id UInt16,
store_id UInt32,
product_id UInt32,
customer_id UInt64,
qty UInt32,
net_amount Decimal(18, 2) CODEC(ZSTD(3)),
discount Decimal(18, 2) CODEC(ZSTD(3)),
_version UInt64,
PROJECTION by_product (SELECT * ORDER BY (product_id, sale_date)),
PROJECTION daily_totals (SELECT sale_date, store_id, sum(net_amount), sum(qty), count() GROUP BY sale_date, store_id)
)
ENGINE = ReplicatedReplacingMergeTree('/clickhouse/tables/{shard}/mart/fact_sales', '{replica}', _version)
PARTITION BY toYYYYMM(sale_date)
ORDER BY (region_id, store_id, sale_date, sale_id)
SETTINGS index_granularity = 8192, storage_policy = 'tiered';
CREATE DICTIONARY mart.dim_product ON CLUSTER '{cluster}'
(
product_id UInt32,
category String,
brand String,
unit_cost Decimal(18, 2)
)
PRIMARY KEY product_id
SOURCE(CLICKHOUSE(TABLE 'stg_product' DB 'staging'))
LAYOUT(HASHED())
LIFETIME(MIN 3600 MAX 4200);
CREATE MATERIALIZED VIEW mart.sales_daily_mv ON CLUSTER '{cluster}'
ENGINE = ReplicatedAggregatingMergeTree('/clickhouse/tables/{shard}/mart/sales_daily', '{replica}')
PARTITION BY toYear(sale_date)
ORDER BY (region_id, store_id, sale_date)
AS SELECT region_id, store_id, sale_date,
sumState(net_amount) AS revenue,
countState() AS orders,
uniqState(customer_id) AS customers
FROM mart.fact_sales
GROUP BY region_id, store_id, sale_date;
-- A dashboard query: dictionary lookup instead of a join, merge of precomputed states instead of a scan
SELECT dictGet('mart.dim_product', 'category', product_id) AS category,
sumMerge(revenue) AS revenue
FROM mart.sales_daily_mv
WHERE region_id = 7 AND sale_date >= today() - 30
GROUP BY category
ORDER BY revenue DESC;Row-level security belongs to the model rather than to the BI tool: a ROW POLICY on region_id scopes every analyst role, and column-masking views serve the same facts to teams that must not see identifiers. Every new mart is reviewed against the fingerprints it will serve with EXPLAIN indexes = 1 before it ships, and its cost is recorded as read rows and read bytes in system.query_log.
Pipelines
Building the database warehousing pipelines: dbt, incremental loads, late data and restatements
ChistaDATA builds staging and marts with dbt on the ClickHouse adapter, so every table has a declared dependency, a test and an owner. Incremental models load only rows whose version exceeds the high-water mark; late-arriving facts and restatements are handled at partition granularity by rebuilding one month from staging and swapping it in, never by rewriting the table.
-- Database warehousing pipeline: dbt incremental model (ClickHouse adapter), staging.stg_sales
{{ config(materialized = 'incremental', engine = 'ReplacingMergeTree(_version)',
order_by = '(store_id, sale_time, sale_id)', partition_by = 'toYYYYMM(sale_time)',
incremental_strategy = 'append') }}
SELECT sale_id, store_id, product_id, customer_id, sale_time, qty, net_amount, discount, _version
FROM {{ source('raw', 'sales_events') }}
{% if is_incremental() %}
WHERE _version > (SELECT max(_version) FROM {{ this }})
{% endif %}
-- Restating one month of the fact table from staging, atomically
INSERT INTO mart.fact_sales_rebuild SELECT ... FROM staging.stg_sales FINAL WHERE toYYYYMM(sale_time) = 202508;
-- Validation query BEFORE the swap: counts and revenue per store must match staging
SELECT store_id, count(), sum(net_amount) FROM mart.fact_sales_rebuild GROUP BY store_id;
ALTER TABLE mart.fact_sales REPLACE PARTITION '202508' FROM mart.fact_sales_rebuild;
-- Validation query AFTER: the live partition now matches
SELECT count(), sum(net_amount) FROM mart.fact_sales WHERE toYYYYMM(sale_date) = 202508;Ingestion into the raw layer follows the same rules as any ChistaDATA platform: the Kafka engine or the official Connect sink for streams, Debezium for CDC from transactional databases, s3() and iceberg() for batch from the lake, with each dataset declared as append-only events or upserted entities so that deduplication is deliberate. The data fabric page covers the four ingestion paths and their consistency guarantees in full.
Support
Database warehousing support in practice: the incidents a warehouse produces
A warehouse fails in ways a transactional database does not. Parts accumulate, dashboards drift onto unindexed columns, a materialized view definition silently stops matching its source, an upgrade changes a default. ChistaDATA’s database warehousing support is built around the incidents we actually see, each with the system table that reveals it and the first runbook step, so that the 24×7 desk starts from evidence rather than from a guess.

-- Database warehousing support: the first three queries the 24x7 desk runs on a "dashboards are slow" ticket
SELECT normalizedQueryHash(query) AS fingerprint, count() AS runs,
quantile(0.95)(query_duration_ms) AS p95_ms,
formatReadableSize(avg(read_bytes)) AS avg_read, avg(read_rows) / greatest(avg(result_rows), 1) AS amplification,
any(substring(query, 1, 100)) AS sample
FROM system.query_log
WHERE type = 'QueryFinish' AND event_time > now() - INTERVAL 1 HOUR
GROUP BY fingerprint ORDER BY runs * p95_ms DESC LIMIT 10;
SELECT database, table, partition, count() AS parts, sum(rows) AS rows, formatReadableSize(sum(bytes_on_disk)) AS size
FROM system.parts WHERE active GROUP BY database, table, partition
HAVING parts > 100 ORDER BY parts DESC LIMIT 20;
SELECT database, table, elapsed, progress, num_parts, formatReadableSize(total_size_bytes_compressed) AS size
FROM system.merges ORDER BY elapsed DESC;Every incident closes with a root-cause note in the engagement record and, where warranted, a runbook update and a new monitoring rule, so the same class of incident is caught earlier the next time. Upgrades are part of support rather than a separate project: each ClickHouse LTS release is qualified against your top fingerprints on a restored backup, rolled one replica per shard at a time with compatibility pinned, and adopted setting by setting with the effect measured in system.query_log.
Managed services
Managed database warehousing: the operating rhythm once the warehouse is live
A warehouse accumulates. Parts, partitions, marts, dashboards and users all grow, and the p95 that was fine at launch degrades quietly until a board dashboard times out. Managed database warehousing from ChistaDATA replaces that drift with a rhythm: daily checks from the 24×7 desk, weekly fingerprint and schema reviews, a monthly service review with the SLA report and a refreshed capacity model, and quarterly health checks, restore and failover drills and cost reviews.

# Managed database warehousing: capacity model refreshed at every monthly service review (illustrative fields)
data_volume_hot_tb: 6.8 # system.parts where disk_name = 'nvme'
data_volume_cold_tb: 41.0 # system.parts where disk_name = 's3_cold'
growth_per_month_tb: 1.9 # 90-day trend from system.parts snapshots
serving_qps_p95: 420 # system.query_log, 5-minute buckets
p95_ms_top20_fingerprints: 380 # weekly review, against SLO 500
concurrent_queries_peak: 140 # system.metrics Query
parts_per_partition_max: 38 # alert at 100, page at 300
keeper_avg_latency_ms: 2 # Keeper mntr, alert at 20
headroom_months: 7 # at current growth on the hot tier
next_action: "add cold volume; review TTL from 90 to 60 days on raw"Cost reporting is per layer and per tenant: hot-tier bytes, cold-tier bytes and object-storage requests, egress, and compute, with the marts and fingerprints that drive each. Recommendations are engineering changes with measured effects (a codec change, a TTL shortened, a projection added, an instance class right-sized), never a generic “optimise”, and each one is applied through the same staging-then-production path as everything else.
Migration
Migrating database warehousing from Redshift, Snowflake or BigQuery into ClickHouse
Legacy database warehousing estates migrate into this architecture one mart at a time, behind the same reconciliation gates ChistaDATA uses for every data movement. The source’s schemas and query history are exported; the top fingerprints are translated and validated with EXPLAIN against the new physical design; history is loaded through Parquet on object storage; the tail is kept current by the same pipelines the new warehouse will run on; and the two warehouses serve the same dashboards in parallel until counts, sums and p95 agree for an agreed window.
| Source | What changes on the way in | What stays |
|---|---|---|
| Amazon Redshift | DISTKEY/SORTKEY become the MergeTree sort key and partition; late-binding views become dictionaries or MVs; VACUUM and WLM disappear | Star schemas, most SQL, the BI layer via the MySQL or PostgreSQL wire protocol |
| Snowflake | Micro-partitions and clustering keys map to partitions and sort keys; Streams and Tasks become Kafka engine tables and MVs; credits become fixed compute | dbt project structure, semi-structured data via JSON type, time travel replaced by versioned staging |
| Google BigQuery | Slot pricing becomes fixed compute; partitioned and clustered tables map directly; scheduled queries become MVs or dbt jobs | Nested and repeated data via Nested and Array types, federated reads via iceberg() |
The full method, including cutover gates and rollback, is on the ClickHouse migration services page; migration and the support contract are normally scoped together so the warehouse is operated by the team that built it.
Governance
Security, governance and compliance in database warehousing
In database warehousing, governance is enforced by the engine, not by convention in each BI tool. Identity from LDAP or SSO maps to ClickHouse roles; grants are per database and table; row policies scope tenants and regions; settings profiles cap what a role can spend and quotas cap how often; every statement lands in system.query_log and every session in system.session_log, retained and shipped to the observability store. TLS is on every port including Keeper, and encryption at rest is the cloud KMS on volumes and buckets.
CREATE ROLE dwh_analyst_emea ON CLUSTER '{cluster}';
GRANT SELECT ON mart.* TO dwh_analyst_emea;
CREATE ROW POLICY emea_scope ON mart.fact_sales FOR SELECT USING region_id IN (7, 8, 9) TO dwh_analyst_emea;
CREATE SETTINGS PROFILE analyst_limits SETTINGS max_memory_usage = 20000000000, max_execution_time = 60 TO dwh_analyst_emea;
CREATE QUOTA analyst_quota FOR INTERVAL 1 HOUR MAX queries = 5000, read_rows = 50000000000 TO dwh_analyst_emea;Compliance evidence is generated from the same tables: retention is a TTL expression and its proof is a query against system.parts; erasure requests under GDPR or DPDP are lightweight deletes by entity with a proof-of-deletion query stored against the ticket; SOC 2 and HIPAA control evidence is exported from system.query_log, system.session_log and the role catalog on a schedule.
Engagement
How ChistaDATA delivers database warehousing: consulting, support and managed services
Consulting
Assessment, architecture, physical design and migration engineering, delivered as scoped statements of work: the reference architecture above sized to your workload, DDL reviewed against your fingerprints, and the pipelines built with your team.
24×7 consultative support
Your team operates the warehouse; ChistaDATA is on call beside it under the escalation matrix (S1 15 min, S2 12 h, S3 24 h, S4 48 h), with monthly service reviews, quarterly health checks and drills, and LTS upgrade planning.
Managed services
ChistaDATA operates the warehouse end to end: the daily-to-quarterly rhythm above, upgrades, capacity, backups, DR drills, cost reporting and SLO reporting, in your account, with your change-approval flow.
Every engagement starts with the pre-engagement questionnaire and a read-only evidence pack, so the first conversation is about your fingerprints and your sizes rather than about generic best practice. Migrations, archival tiers for transactional databases and data fabric platforms are scoped from the same assessment.
Industry patterns
Database warehousing patterns by industry
The architecture is the same across industries; what differs is which marts are latency-critical, which dimensions change fastest, and which governance rules dominate. These are reference patterns, not client claims, sized per organisation during the assessment.
E-commerce and retail
Order and clickstream facts, product and store dimensions refreshed hourly from the master-data system, sell-through and margin marts as aggregate states, per-tenant row policies for marketplace sellers.
AdTech and digital marketing
Impression and bid facts at billions of rows a day through multiple Kafka consumers per replica, campaign dimensions as dictionaries, projections for the two dominant report shapes, quota-governed self-service.
Financial services
Transaction facts with seven-year retention on the cold tier, versioned account and counterparty dimensions for point-in-time reporting, row policies per legal entity, evidence exports for regulators.
IoT and telemetry
Device telemetry with DoubleDelta and Gorilla codecs, daily partitions tiered to object storage, asset dimensions from the CMMS, predictive-maintenance marts per asset class.
Gaming
Session and event facts keyed by player and time, live-ops marts refreshed on insert for real-time dashboards, cohort and retention marts by day, A/B assignment dimensions as dictionaries.
SaaS and platforms
Customer-facing embedded analytics through the gateway with per-tenant row policies, usage and billing marts reconciled against the transactional system nightly, feature tables for churn models.
FAQ
Database warehousing on ClickHouse: questions we hear most often
Is database warehousing on ClickHouse the same as running ClickHouse Cloud?
No. The warehouse described here runs on 100% open-source ClickHouse in your own account, deployed by an open-source operator with your object storage; ChistaDATA provides the engineering, support and operations. There is no proprietary layer, and nothing prevents you from taking the platform in-house later.
Can we keep dbt, our BI tools and our existing models when moving database warehousing to ClickHouse?
Yes. dbt runs on the ClickHouse adapter with the same project structure; Grafana, Superset, Tableau, Power BI and JDBC tools connect through the native, HTTP, MySQL or PostgreSQL protocols. Model definitions are translated during migration, with the physical design (sort keys, partitions, dictionaries, marts) rebuilt for ClickHouse.
How fresh can the warehouse be?
Seconds through the Kafka engine or the Connect sink for streams and CDC, minutes to hours for batch loads from the lake. Freshness is declared per dataset, measured continuously and alerted on when missed; the assessment sets targets from what each consumer actually needs.
What does the database warehousing support contract cover?
Incident response on the whole estate under the S1–S4 escalation matrix, root-cause analysis, LTS upgrade qualification and rollout, schema and query reviews for new marts, backup and DR drills, monthly service reviews and quarterly health checks. Managed services add day-to-day operation of all of it.
How do you handle late data and restatements?
At partition granularity. Facts are partitioned by month; a late batch or a restatement rebuilds the affected month from versioned staging into a rebuild table, is validated by count and sum per key, and is swapped in with REPLACE PARTITION. The table is never rewritten and dashboards never see a half-loaded month.
Next step
Start with your fingerprints, not a platform pitch
A database warehousing assessment from ChistaDATA takes your query history, your data volumes and your freshness needs and returns a physical design, a sizing and a support scope you can hold the warehouse to. If the numbers say ClickHouse is the right engine, the same engineers build it, migrate into it and operate it under 24×7 support or as the managed team; if they say your cloud warehouse should stay, the assessment says that too.
Further reading: ClickHouse migration services · Data fabric on cloud-native ClickHouse · RDBMS archival with ChistaDATA Fabric · AggregatingMergeTree · ClickHouse dictionaries · dbt-clickhouse