Choosing a ClickHouse primary key and ordering key
Picking ORDER BY columns for a MergeTree table: filter columns first, cardinality order, compression effects, and how to test a key change on a copy before migrating production data.

Schema, ingestion and query techniques that keep self-managed ClickHouse fast: ordering keys, partitions, skip indexes, materialized views, projections, inserts, updates and resource controls.
Picking ORDER BY columns for a MergeTree table: filter columns first, cardinality order, compression effects, and how to test a key change on a copy before migrating production data.
When to partition, by what, and how coarse: partitions for retention and data management, the cost of too many partitions, and aligning partitions with TTL.
When minmax, set and Bloom filter skip indexes help, how to confirm they are used with EXPLAIN, and why they come after the ordering key and materialized views.
Precomputing aggregates at insert time with incremental materialized views: target table engines such as AggregatingMergeTree, backfilling, chaining views, and the insert cost they add.
Scheduled rebuilds with REFRESH EVERY for queries that cannot be incremental: full replace versus APPEND, dependencies between views, and scheduling heavy refreshes off-peak.
Using projections as hidden alternate orderings or pre-aggregations that ClickHouse picks automatically, and when a materialized view is the better choice.
Replacing joins with in-memory dictionaries loaded from ClickHouse, PostgreSQL, MySQL, HTTP or files: layouts, refresh lifetimes, memory use, and enrichment at insert time.
Reducing join cost in ClickHouse: denormalizing frequently queried attributes, dictionaries, join algorithms and table order, and using materialized views instead of large joins.
Configuring async_insert for many agents sending small batches: flush thresholds, wait_for_async_insert and durability, deduplication, and monitoring buffer flushes.
Choosing between lightweight UPDATE and DELETE, ALTER mutations, ReplacingMergeTree and partition drops: visibility, cost on large tables, and patterns for frequent corrections.
Handling updated and duplicate rows with ReplacingMergeTree: version columns, eventual deduplication, FINAL at query time, and why OPTIMIZE FINAL should not be routine.
When to use the JSON type, typed columns or a String column for JSON payloads: subcolumn storage, query performance, and schema design for unpredictable keys.
Caching repeated dashboard queries with use_query_cache: entry lifetimes, stale results, cache size limits, and which queries should never be cached.
Keeping ingestion, dashboards and ad hoc queries from starving each other: CPU, IO and memory resources, workload hierarchies, weights and priorities, and concurrency limits.
A repeatable process for slow ClickHouse queries: finding them in system.query_log, EXPLAIN and rows read, isolating bottlenecks, and choosing between schema, index and query fixes.
Setting per-query and server memory limits, external GROUP BY and sort thresholds, and finding the queries that use the most memory before they fail.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.