Skip to content

perf(snowflake): cut per-model statement overhead, and write a Rules-failed compile to target/compiled-failed - #1265

Merged
kvlonge merged 13 commits into
mainfrom
perf/snowflake-statements
Oct 28, 2026
Merged

kvlonge merged 13 commits into
mainfrom
perf/snowflake-statements

Conversation

@kvlonge

@kvlonge kvlonge commented Oct 28, 2026

Copy link
Copy Markdown
Contributor

Why

Each Snowflake statement is a round trip, and builds spent many on housekeeping: drops of object kinds never created, INFORMATION_SCHEMA reads, identical fingerprint rows, per-target scenario cleanup. A Rules-failed compile also wrote into target/compiled/ and needed a side record.

Changes

  • Drop and replace only the table kinds a build creates.
  • Snowflake: per-run SHOW schema listings and retention; session-only statements such as QUERY_TAG keep them.
  • Fingerprint rows are appended only when the identity changes. Skipping is off with model migration history: rename matching reads fingerprint times.
  • Scenario cleanup lists targets by name prefix and reuses confirmed results.
  • Kept: merge/microbatch column reads (warehouse types), the DuckDB staging drop after a swap, the freshness LAST_ALTERED read, the sqb test path.
  • A compile whose Rules fail writes its SQL to target/compiled-failed/ (with the not-buildable header) and never touches target/compiled/. The next passing compile deletes it, and the report names each failing file. target/compiled-models.txt is removed.
  • The compile after a Rules-failed compile runs in full, since that compile writes no SQL tests, functions or audits.
  • Goldens:
    • failure/rule-custom-finding.json: model SQL moves from compiled to compiled_failed.
    • failure/rule-unused-cte.json: same, with the header.
    • failure/rule-unused-cte-after-variable-and-macro.json: same, with the header.

Verification

DuckDB housekeeping statements, synthetic orders project:

Command Before After
build 1st / 2nd / 3rd 72 / 81 / 72 56 / 60 / 55
scenario 15 12

Snowflake counts confirmed on a scratch schema. make test, make check-ci and the build, scenario, adapters and compile E2E directories pass; new CLI statement-count, compiled-failed sequence and offline Snowflake tests.

Staging and delta tables are created with CREATE OR REPLACE where the adapter replaces, dropped only as tables, kept between microbatch batches that replace them, and counted only when DML reports no row count. A table without an enforced contract skips the staging column read.
…a listings

A run lists a schema with SHOW TABLES and SHOW VIEWS once it looks up a second relation there, and reads retention with SHOW instead of INFORMATION_SCHEMA. Promotion reads the destination again when another session changed it.
A build sets up each fingerprint table once and skips rows identical to the latest one, except in projects with model migration history, where rename matching compares rows with rename events.
Scenario cleanup lists the namespace with one SHOW TERSE OBJECTS on Snowflake, drops each relation by its listed kind, and answers the scenario's later existence checks for relations it confirmed absent.
…failed/

A compile whose Rules fail writes every model's SQL to target/compiled-failed/,
laid out like target/compiled/, with the not-buildable header on failing
models, and never touches target/compiled/. Each failing compile replaces the
folder as a whole and the next passing compile deletes it, so target/compiled/
always holds exactly the last passing compile. The report names each failing
model's file. The record of written model files is gone.

Compile reuse, delta compiles and delta verification cover the new folder:
a failing delta writes the models it did not rerun from the stored compile, and
a passing delta after a failed compile brings target/compiled/ up to date.
A compile whose Rules fail writes no SQL tests, functions or audits, so a
delta on top of it left those files as an older passing compile wrote them.
The next compile after a Rules failure now compiles in full, and the delta
paths that restored models from the failed compile's SQL are removed.

Delta tests whose stored project failed its Rules by accident now give their
custom Rules a harness case, or turn off the built-in Rules that cannot parse
PIVOT models, so they keep exercising deltas.
A compile whose Rules fail removes target/manifest.json, but with --manifest
its report still said it wrote one. The text and JSON reports now leave the
manifest out after a Rules failure.
A per-model query tag hook such as ALTER SESSION SET QUERY_TAG, and USE
WAREHOUSE, change no relation and no name resolution, but they invalidated
every cached listing, so the next lookup listed the whole schema again. Setting
or resetting one parameter known not to affect name resolution, and changing
the warehouse, now leave the cache alone. Other session parameters, USE of a
database, schema or role, and ambiguous statements such as CALL or EXECUTE
IMMEDIATE still invalidate it.
…several parameters

An unquoted session parameter value ended only at whitespace, so a statement
setting a neutral parameter followed by a comma and one that changes name
resolution kept the cache. An unquoted value now ends before a comma or an
equals sign, and such a statement clears the cache.
@kvlonge
kvlonge enabled auto-merge (squash) October 28, 2026 16:09
The view whose post hook drops the fingerprint table now reads every other
model, so they all record before the drop and the expected rows no longer
depend on which independent model the scheduler runs first.
@kvlonge
kvlonge merged commit 8d75270 into main Oct 28, 2026
48 checks passed
@kvlonge
kvlonge deleted the perf/snowflake-statements branch October 28, 2026 18:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant