Skip to content

perf(gas_solana_tx_fees): merge compute_limit + compute_unit_price into single compute_budget table#9880

Merged
0xRobin merged 4 commits into
mainfrom
robin/cur2-2801-perfgas_solana_tx_fees_current-restructure-dual
Jul 17, 2026
Merged

perf(gas_solana_tx_fees): merge compute_limit + compute_unit_price into single compute_budget table#9880
0xRobin merged 4 commits into
mainfrom
robin/cur2-2801-perfgas_solana_tx_fees_current-restructure-dual

Conversation

@0xRobin

@0xRobin 0xRobin commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Summary

gas_solana_tx_fees_current (and its 17 quarterly backfills) joins two upstream ComputeBudget decodings — gas_solana_compute_limit and gas_solana_compute_unit_price — once each, keyed on (tx_id, block_date). Both models decode the same source (solana.instruction_calls, ComputeBudget111...) with identical filters except a single opcode byte (0x02 vs 0x03). This PR merges them into one upstream table, gas_solana_compute_budget, keyed on (block_date, block_slot, tx_id), with one row per tx and two columns (compute_limit, compute_unit_price, either nullable). The macro then joins once. The old model names remain as backward-compat views over the new table, so external Dune users of dune.gas_solana.compute_limit / dune.gas_solana.compute_unit_price see no contract change.

Ref: CUR2-2801

Why (baseline from CUR2-2801, 24h @ 2026-06-13)

  • 40 runs/day, avg 106 s wall, ~3.1 GB scan/run — 6.1 CPU-hrs/day (~5.6% of cluster).
  • Representative query 20260612_191937_01377_p49px: 7,265 CPU-s, 41.2 GB IO, 1,248 s wall, peak memory 155 GB total / 55.4 GB per task (memory-pressure warning), MERGE writes ~168 rows.
  • Dominant cost: two ~200M-row hash joins (solana.transactions LEFT JOIN compute_limit LEFT JOIN compute_unit_price). LookupJoin stage ≈ 45% CPU.

Design

New model — dbt_subprojects/solana/models/_sector/gas/gas_solana_compute_budget.sql

  • schema='gas_solana', alias='compute_budget', partition_by=['block_date','block_hour'], materialized='incremental', file_format='delta', incremental_strategy='delete+insert', unique_key=['block_date','block_slot','tx_id'].
  • Body reads solana.instruction_calls once with bytearray_substring(data,1,1) IN (0x02, 0x03) and pivots: MAX(CASE WHEN op = 0x02 THEN val END) AS compute_limit, MAX(CASE WHEN op = 0x03 THEN val END) AS compute_unit_price, GROUP BY tx_id, block_date, block_hour, block_time, block_slot, tx_index.

Backward-compat views (contract-preserving)

  • gas_solana_compute_limitmaterialized='view', SELECT tx_id, block_date, block_hour, block_time, block_slot, tx_index, compute_limit FROM ref('gas_solana_compute_budget') WHERE compute_limit IS NOT NULL.
  • gas_solana_compute_unit_price → symmetric, WHERE compute_unit_price IS NOT NULL.

Macro edit — dbt_subprojects/solana/macros/_sector/gas/solana_tx_fees_macro.sql

  • Replaced the two LEFT JOIN gas_solana_compute_limit cl + LEFT JOIN gas_solana_compute_unit_price up with a single LEFT JOIN gas_solana_compute_budget cb.
  • cb.compute_limit and cb.compute_unit_price feed the existing COALESCE(..., 200000) / COALESCE(.../1e6, 0) expressions unchanged. Base fee, breakdown maps, block-leaders join, prices join, and tx_fee_currency are untouched.
  • Applies to gas_solana_tx_fees_current and all 17 quarterly backfills.

Not in this PR (deliberate):

  • The secondary lever from CUR2-2801 (double prices.usd_forward_fill scan / minute predicate not pushed) is left alone — different failure mode, worth a separate change.
  • The pre-existing schema-yaml #todo placeholders on the view stubs are left as-is.

Evidence (live delta_prod, 2026-06-13)

Sizing (single production day):

Metric Rows
delta_prod.gas_solana.compute_limit (op 0x02) 86,657,892
delta_prod.gas_solana.compute_unit_price (op 0x03) 74,648,223
Distinct (block_date, tx_id) in merged table 89,353,063
Both opcodes on the same tx 71,952,053
Only compute_limit 14,705,839
Only compute_unit_price 2,695,171

Cost math (unit day):

Current Merged Δ
instruction_calls scans in the compute build 2 × filtered (86.7M + 74.6M rows kept) 1 × filtered (161.3M rows kept) ~50% source IO
Hash join keys in the fee build 86.7M + 74.6M across 2 joins 89.4M across 1 join ~45% key reduction
Rows across both compute tables 161.3M 89.4M -45%

Aligned with the -30-40% CPU / halved-join-memory estimate in the issue.

Bit-identical equivalence (delta_prod, 2026-06-13):

WITH merged AS (
    SELECT tx_id, block_date,
           MAX(CASE WHEN op = 0x02 THEN val END) AS compute_limit,
           MAX(CASE WHEN op = 0x03 THEN val END) AS compute_unit_price
    FROM (
        SELECT tx_id, block_date,
               bytearray_substring(data, 1, 1) AS op,
               bytearray_to_bigint(bytearray_reverse(bytearray_substring(data, 2, 8))) AS val
        FROM delta_prod.solana.instruction_calls
        WHERE block_date = DATE '2026-06-13'
          AND executing_account = 'ComputeBudget111111111111111111111111111111'
          AND executing_account_prefix = 'Co'
          AND bytearray_substring(data, 1, 1) IN (0x02, 0x03)
          AND inner_instruction_index IS NULL
    ) x
    GROUP BY tx_id, block_date
),
separate AS (
    SELECT COALESCE(cl.tx_id, up.tx_id) AS tx_id,
           COALESCE(cl.block_date, up.block_date) AS block_date,
           cl.compute_limit,
           up.compute_unit_price
    FROM (SELECT tx_id, block_date, compute_limit
          FROM delta_prod.gas_solana.compute_limit
          WHERE block_date = DATE '2026-06-13') cl
    FULL OUTER JOIN (SELECT tx_id, block_date, compute_unit_price
                     FROM delta_prod.gas_solana.compute_unit_price
                     WHERE block_date = DATE '2026-06-13') up
      ON cl.tx_id = up.tx_id AND cl.block_date = up.block_date
)
SELECT
    (SELECT COUNT(*) FROM (SELECT * FROM merged  EXCEPT ALL SELECT * FROM separate) x) AS merged_minus_separate,
    (SELECT COUNT(*) FROM (SELECT * FROM separate EXCEPT ALL SELECT * FROM merged  ) x) AS separate_minus_merged,
    (SELECT COUNT(*) FROM merged  ) AS n_merged,
    (SELECT COUNT(*) FROM separate) AS n_separate

Result:

merged_minus_separate | separate_minus_merged | n_merged   | n_separate
        0             |          0            | 89,353,063 | 89,353,063

The merged model reproduces the exact (tx_id, block_date, compute_limit, compute_unit_price) cross-product of the two existing tables — bit-identical in both directions.

Compile check

uv run dbt compile --profile spellbook-trino --project-dir dbt_subprojects/solana/ \
  --select gas_solana_compute_budget gas_solana_compute_limit gas_solana_compute_unit_price \
           gas_solana_tx_fees_current gas_solana_tx_fees_2024_q4

Exit 0. Compiled gas_solana_tx_fees_current shows the single LEFT JOIN ... gas_solana_compute_budget cb in place of the previous two joins. dbt build intentionally not run — CI handles it.

Files changed

  • new dbt_subprojects/solana/models/_sector/gas/gas_solana_compute_budget.sql
  • dbt_subprojects/solana/models/_sector/gas/gas_solana_compute_limit.sql — now a view over gas_solana_compute_budget
  • dbt_subprojects/solana/models/_sector/gas/gas_solana_compute_unit_price.sql — now a view over gas_solana_compute_budget
  • dbt_subprojects/solana/macros/_sector/gas/solana_tx_fees_macro.sql — dual → single JOIN
  • dbt_subprojects/solana/models/_sector/gas/_schema.yml — full metadata + tests for gas_solana_compute_budget

…olana_compute_budget

Introduce gas_solana_compute_budget: one incremental delta table keyed
(block_date, block_slot, tx_id) with both compute_limit (opcode 0x02) and
compute_unit_price (opcode 0x03) columns, populated from a single filtered
scan of solana.instruction_calls.

Rewrite gas_solana_compute_limit and gas_solana_compute_unit_price as views
over the merged table so external consumers of dune.gas_solana.compute_limit
and dune.gas_solana.compute_unit_price keep the same column contract.

Update solana_tx_fees_macro (used by gas_solana_tx_fees_current and the 17
quarterly backfills) to LEFT JOIN once against gas_solana_compute_budget
instead of joining compute_limit and compute_unit_price separately.

Baseline (2026-06-13): 86.66M limit + 74.65M price rows across two
~200M-key hash joins. Merged: 89.35M rows in one table, one hash join.
Live-engine EXCEPT ALL both ways = 0 (n=89,353,063 on both sides).

Ref CUR2-2801.
@cursor

cursor Bot commented Jul 8, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Touches the Solana gas fee pipeline and fee math inputs; logic is intended to be equivalent but wrong pivot/join keys would skew priority fees across high-volume models.

Overview
Merges the two separate ComputeBudget decode models into one incremental gas_solana_compute_budget table that scans solana.instruction_calls once (opcodes 0x02 / 0x03) and pivots to compute_limit and compute_unit_price per (block_date, block_slot, tx_id).

gas_solana_compute_limit and gas_solana_compute_unit_price are replaced as physical incremental tables with views over gas_solana_compute_budget (filtered with IS NOT NULL so existing row sets stay the same for external consumers).

solana_tx_fees_macro now joins once to gas_solana_compute_budget instead of two joins; prioritization fee COALESCE logic is unchanged. Schema docs and uniqueness tests were added for the new model.

Reviewed by Cursor Bugbot for commit a2171a3. Configure here.

@github-actions github-actions Bot added WIP work in progress dbt: solana covers the Solana dbt subproject labels Jul 8, 2026
@0xRobin

0xRobin commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

bugbot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit a2171a3. Configure here.

Adds `{% if target.name == 'ci' %} AND <partition> >= current_date - interval '3' day` to source scans in the two files modified by this PR so the solana CI job (state:modified.macros fan-out to all 18 tx_fees models) prunes instead of full-scanning and completes within the 90-minute CI cap.

- gas_solana_compute_budget.sql: bound instruction_calls block_date in CI.
- solana_tx_fees_macro.sql: bound transactions t.block_date, compute_budget cb.block_date, block_leaders b.date, prices.usd_forward_fill p.minute in CI.

Prod SQL unrendered: target.name != 'ci' so the guards render to nothing.
Partition columns confirmed pruning on delta_prod: instruction_calls/block_date (~53s for 3-day slice), transactions/block_date (~5s), prices.usd_forward_fill/minute (~2s).

Verified with `dbt parse --profile spellbook-trino --project-dir dbt_subprojects/solana/` (exit 0). Ref CUR2-2801.
@0xRobin
0xRobin marked this pull request as ready for review July 14, 2026 07:50
@github-actions github-actions Bot added ready-for-review this PR development is complete, please review and removed WIP work in progress labels Jul 14, 2026
@0xRobin
0xRobin requested review from a team and jeff-dude July 15, 2026 10:43

@jeff-dude jeff-dude left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

approved with minor addition

@jeff-dude jeff-dude added ready-for-merging and removed ready-for-review this PR development is complete, please review labels Jul 16, 2026
@0xRobin
0xRobin merged commit 011255e into main Jul 17, 2026
11 checks passed
@0xRobin
0xRobin deleted the robin/cur2-2801-perfgas_solana_tx_fees_current-restructure-dual branch July 17, 2026 07:43
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 17, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

dbt: solana covers the Solana dbt subproject ready-for-merging

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants