Quarry

Performance

What Quarry does and does not do for query performance.

Quarry is a query builder. It does not add its own performance layer on top of ClickHouse.

That means Quarry does not:

  • optimize your schema
  • rewrite queries for speed
  • infer PREWHERE
  • decide when FINAL is appropriate
  • choose insert batch sizes for you
  • tune server settings automatically

Quarry mostly gives you typed access to the SQL features ClickHouse already has.

What this means in practice

For performance work, use the same judgment you would use with handwritten ClickHouse SQL.

Typical ClickHouse performance concerns still apply:

  • schema design
  • partitioning and sort keys
  • filtering strategy, including PREWHERE vs WHERE
  • whether FINAL is necessary
  • aggregation memory use, including functions such as groupArray(...)
  • insert batch sizing
  • query settings such as max_threads

Quarry's role

Quarry can help you inspect the final SQL with toSQL(), but it does not try to be an optimizer.

TypeScript
const compiled = db
  .selectFrom("event_logs as e")
  .select("e.user_id")
  .where("e.event_type", "=", "signup")
  .toSQL();

If performance matters, inspect the SQL Quarry produced and then apply normal ClickHouse performance analysis to that query.

TypeScript and large schemas

Compiler performance is separate from ClickHouse execution performance. Quarry validates a selected source directly and avoids enumerating every possible table alias for large schemas. The improvement is part of the exported declarations, so downstream applications benefit on supported TypeScript versions without upgrading their compiler.

Repository maintainers can reproduce the consumer checks with:

Terminal
pnpm test:performance
node scripts/check-type-performance.mjs --native

The fixtures import built declarations and cover 710 database objects, 1,000 distinct wide tables, service-specific schemas, joined selections, CTE chains, and array operations. CI records timings and checks an instantiation budget under pinned TypeScript 6.0.2. Wall time is not a CI gate because shared runners vary. Counter values are only comparable under the same compiler version.

The standalone core/CLI checker also runs under TypeScript 7. Core declarations use tsdown’s Oxc emit with isolatedDeclarations; the classic TypeScript 6 dependency remains for validation and tooling. Docs retain TypeScript 5.9. Consumers can use TS 5.9, 6, or 7 independently of the compiler used to build Quarry.

For application code, select only needed columns, keep exported row/query types understandable, and profile a representative consumer with --extendedDiagnostics before changing types. Deep generic wrappers and unusually wide schemas can have different costs from these fixtures. Do not disable strictness to hide a slowdown.

Give each service the schema it needs

Keep one generated schema and derive a smaller type for query modules that use only a few tables:

TypeScript
import { createClickHouseDB } from "quarry";
import type { DB } from "./generated-schema";

type AnalyticsDB = Pick<DB, "events" | "users">;
const analytics = createClickHouseDB<AnalyticsDB>({ client });

const query = analytics.selectFrom("events as e")
  .innerJoin("users as u", "e.user_id", "u.id")
  .select("u.id", "e.event_type");

This reuses your client and preserves the generated column types. TypeScript validates the selected table names, so schema regeneration still catches a removed or renamed table. Other services can keep the full DB or choose a different subset. The full schema remains available for introspection and other modules.

The performance fixture includes both full and scoped builders over the same 1,000-table schema. Narrowing to the eleven tables used by its queries reduced check time in local experiments; actual gains depend on your schema and queries. There is no benefit from narrowing if the module needs every table.

A Pick type limits the builder's compile-time API. It does not restrict the ClickHouse connection's permissions or authorize tenant access.

On this page