Skip to content

perf: prune partitions in the remaining report queries - #2351

Open
tlangton3 wants to merge 3 commits into
elementary-data:masterfrom
tlangton3:perf/partition-pruning-report-queries
Open

perf: prune partitions in the remaining report queries#2351
tlangton3 wants to merge 3 commits into
elementary-data:masterfrom
tlangton3:perf/partition-pruning-report-queries

Conversation

@tlangton3

@tlangton3 tlangton3 commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

What

The report queries filter their largest tables with edr_datediff(edr_cast_as_timestamp(col), now, 'day') < days_back. On BigQuery, a function applied to the column defeats partition pruning, so these scan all history however small days_back is.

This is the same defect #1940 fixed for test_result_rows, applied to the remaining sites — and it generalises that fix so the pattern is in one place instead of copied per macro.

Measured

A 7-day lookback selecting a single column, on tables exactly as they are — no repartitioning needed to get this:

Table Before After
elementary_test_results (12M rows, 13GB) 1,368 MB 13.68 MB
dbt_run_results (17M rows, 41GB) 1,627 MB 63.56 MB
test_result_rows (26M rows, 41GB) 1,060 MB 101 MB

For scale, an unfiltered scan of elementary_test_results reads 1,279 MB: the current predicate reads more than no filter at all, because it also pays to read the column it filters on.

How

A dispatched days_back_filter macro. default__ renders exactly the predicate these queries have always used, so nothing changes off BigQuery. bigquery__ compares the column directly and adds a bound on the partition column.

Applied to both CTEs of current_tests_run_results_query, and to get_result_rows_agate — which lets that macro's bigquery__ override go away. #1940 had to duplicate the entire body just to change one where clause; with the dispatch in the predicate helper, the two copies collapse back into one.

About the redundant-looking bound

The BigQuery variant emits e.g. detected_at > X and created_at > X-1day. The second predicate is implied by the first — it exists only because BigQuery prunes on the raw partition column and nothing else. It is needed when the filtered column is not the partition column, and unavoidable for dbt_run_results, which stores generated_at and execute_completed_at as strings: those need a cast, and no cast predicate can ever prune.

It cannot exclude a row the real predicate wants, because created_at is stamped by insert_rows from edr_current_timestamp() at insert time and never read from the row payload — so it is always at or after the event timestamp it guards. Checked over 17.2M rows: created_at - generated_at >= 0s, created_at - execute_completed_at >= +5s, created_at - detected_at >= 0s across 12M and 26M row tables, zero violations of any.

Since those two timestamps are not read from the same clock — one warehouse-side, one client-side — the bound is given a day of slack rather than the same bound, so client drift cannot cost a row. Pruning is at day granularity, so that is at most one extra partition; on the figures above it measured as no difference at all, the real predicate being the binding constraint.

Not included

get_models_runs has the same defect and is the largest single win, but it reads the model_run_results view, which does not expose created_at — so it has no prunable column until elementary-data/dbt-data-reliability#1057 lands. Deliberately left for a follow-up rather than shipped broken.

get_source_freshness_results and can_upload_source_freshness carry the same shape. I have no source-freshness data to measure, so I have not touched them — happy to if you would like them included.

Testing

Rendering verified for each branch of the macro: timestamp column, string column (cast applied), the column being the partition column itself (bound correctly suppressed), a string-typed days_back, and the default path (byte-identical semantics to the predicate it replaces). Resulting predicates dry-run against real tables for the figures above. typos clean; the repo's Python hooks do not apply to .sql.

Summary by CodeRabbit

  • Performance

    • Improved date-range filtering for recent test and run results.
    • BigQuery queries can make better use of partitioned data, potentially reducing scan volume and improving response times.
  • Consistency

    • Standardized result filtering across supported database environments.
    • Preserved filtering by valid result IDs and grouping of returned rows.

`current_tests_run_results_query` filters both of its large CTEs with
`edr_datediff(edr_cast_as_timestamp(col), now, 'day') < days_back`. On BigQuery a
function applied to the column defeats partition pruning, so both scan all
history however small `days_back` is.

Adds a dispatched `days_back_filter` macro: the default implementation renders
exactly the predicate above, so nothing changes off BigQuery, while `bigquery__`
compares the column directly and adds a bound on the partition column.

Measured with a 7-day lookback, selecting a single column, on tables as they
already are — no repartitioning needed to get this:

    elementary_test_results (12M rows, 13GB)   1,368 MB -> 13.68 MB
    dbt_run_results         (17M rows, 41GB)   1,627 MB -> 63.56 MB

For reference, an unfiltered scan of elementary_test_results reads 1,279 MB: the
current predicate reads *more* than no filter at all, since it also pays to read
the column it filters on.

The bound on `created_at` looks redundant — it is implied by the first predicate —
but BigQuery only prunes on the raw partition column, and `execute_completed_at`
is stored as a string, so a cast is unavoidable there and no predicate on it can
prune. dbt_run_results is not even partitioned on the warehouse measured above;
the 26x comes from block-level pruning on `created_at` alone, and partitioning it
would improve that further.

The bound is also safe: `created_at` is written at or after both columns, so any
row satisfying the first predicate satisfies the bound. Verified over 17.2M rows —
`created_at - generated_at` >= 0s, `created_at - execute_completed_at` >= 5s, and
zero rows violating either.

The guard is given a day of slack rather than the same bound: `created_at` is
stamped by the warehouse at insert while the columns it guards come from the dbt
client, so the two are not the same clock. Pruning is at day granularity, so the
slack costs at most one extra partition — measured as no difference at all on the
figures above, since the real predicate is the binding constraint.
…ilter

elementary-data#1940 gave this macro a `bigquery__` override that duplicated the whole body just
to change its `where` clause. Now that `days_back_filter` dispatches on the
predicate itself, the two copies collapse back into one and the dispatch
disappears.

Behaviour is unchanged on every adapter: `default__days_back_filter` renders the
datediff form the original had, and `bigquery__days_back_filter` renders the
direct comparison the override had.

It also gains the `created_at` bound. test_result_rows declares no partitioning
today, so the direct comparison on `detected_at` was relying on block-level
pruning alone; the bound takes a 7-day lookback from 1,060 MB to 101 MB on a 26M
row / 41GB copy of that table, and improves further once it is partitioned.
@github-actions

Copy link
Copy Markdown
Contributor

👋 @tlangton3
Thank you for raising your pull request.
Please make sure to add tests and document all user-facing changes.
You can do this by editing the docs files in this pull request.

@coderabbitai

coderabbitai Bot commented Sep 10, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: b8c15093-9a59-4643-8ce6-dd9dec82099c

📥 Commits

Reviewing files that changed from the base of the PR and between 73cf8fc and e8a18ba.

📒 Files selected for processing (1)
  • elementary/monitor/dbt_project/macros/utils/days_back_filter.sql
🚧 Files skipped from review as they are similar to previous changes (1)
  • elementary/monitor/dbt_project/macros/utils/days_back_filter.sql

Included review availability: Your plan provides up to 8 included reviews per hour; 7 remain after this review.


📝 Walkthrough

Walkthrough

The change adds an adapter-dispatched days_back_filter macro. Result queries use it for date filtering, with BigQuery-specific partition pruning and string-column handling.

Changes

Days-back filtering

Layer / File(s) Summary
Add adapter-aware days-back filtering
elementary/monitor/dbt_project/macros/utils/days_back_filter.sql
Adds default and BigQuery implementations for timestamp windows, optional string casting, and partition bounds.
Apply filtering to result queries
elementary/monitor/dbt_project/macros/base_queries/current_tests_run_results_query.sql, elementary/monitor/dbt_project/macros/get_result_rows_agate.sql
Updates result queries to use days_back_filter and removes adapter-specific agate implementations.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to e8a18

The reviewed change has no established merge-blocking risk.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the primary change: applying partition-pruning filters to the remaining report queries. It is concise and specific.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@tlangton3

Copy link
Copy Markdown
Contributor Author

Follow-up that builds on this: #2352 applies the same days_back_filter to get_models_runs. Left as a draft because it additionally needs elementary-data/dbt-data-reliability#1057 to expose created_at on the model_run_results view.

Only 4 of 48 macros here carry a doc block and none exceeded 12 lines; this had
24. Keeps the two things a reader cannot infer and would otherwise 'tidy' away —
that the second bound is what makes BigQuery prune, and that its day of slack is
deliberate — and drops the rest, which the PR description already covers.

Also builds the predicate by joining a list rather than capturing a {% set %}
block, so the compiled SQL is a single line instead of carrying the macro's
indentation and blank lines into every query.
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