cancel
Showing results forย 
Search instead forย 
Did you mean:ย 
Warehousing & Analytics
Engage in discussions on data warehousing, analytics, and BI solutions within the Databricks Community. Share insights, tips, and best practices for leveraging data for informed decision-making.
cancel
Showing results forย 
Search instead forย 
Did you mean:ย 

SQL Query billing

anmolhhns
New Contributor III

Is there any way to find a cost of one single query? i can't find any table in system catalog to connect a query with usage to find the exact cost of one query run in sql warehouse?

2 REPLIES 2

GabFernandes
Contributor

Hi@anmolhhns,

There is no direct per-query cost field in Databricks system tables today. Here's why, and how to estimate it.

The gap:

  • system.billing.usage โ€” records DBU consumption at the warehouse level per hour (keyed by usage_metadata.warehouse_id + hourly time window). No statement_id field.
  • system.query.history โ€” has detailed per-query metrics (statement_id, durations, bytes read, etc.) but no cost/DBU column.

There's no direct join key between billing and an individual query.

How to estimate per-query cost (proportional allocation):

The best proxy for "compute work done" by a single query is total_task_duration_ms โ€” defined as "the sum of all task durations across all cores of all nodes". You can allocate the hourly warehouse DBU cost proportionally to each query's share of total task time in that hour:

WITH hourly_cost AS (
  SELECT
    usage_metadata.warehouse_id AS warehouse_id,
    DATE_TRUNC('hour', usage_start_time) AS usage_hour,
    SUM(usage_quantity) AS total_dbus,
    SUM(usage_quantity * lp.pricing.default) AS total_cost_usd
  FROM system.billing.usage u
  LEFT JOIN system.billing.list_prices lp
    ON u.sku_name = lp.sku_name AND lp.price_end_time IS NULL
  WHERE usage_metadata.warehouse_id IS NOT NULL
    AND usage_date >= CURRENT_DATE - INTERVAL 7 DAY
  GROUP BY 1, 2
),



hourly_query_work AS (
  SELECT
    compute.warehouse_id AS warehouse_id,
    DATE_TRUNC('hour', start_time) AS query_hour,
    statement_id,
    executed_by,
    statement_text,
    total_task_duration_ms,
    total_duration_ms,
    SUM(total_task_duration_ms) OVER (
      PARTITION BY compute.warehouse_id, DATE_TRUNC('hour', start_time)
    ) AS total_work_in_hour
  FROM system.query.history
  WHERE start_time >= CURRENT_DATE - INTERVAL 7 DAY
    AND execution_status = 'FINISHED'
    AND total_task_duration_ms > 0
)



SELECT
  q.statement_id,
  q.executed_by,
  q.query_hour,
  q.total_duration_ms,
  q.total_task_duration_ms,
  -- Proportional share of the hour's DBU cost
  ROUND(
    c.total_dbus * (q.total_task_duration_ms / q.total_work_in_hour), 4
  ) AS estimated_dbus,
  ROUND(
    c.total_cost_usd * (q.total_task_duration_ms / q.total_work_in_hour), 4
  ) AS estimated_cost_usd,
  LEFT(q.statement_text, 100) AS query_preview
FROM hourly_query_work q
JOIN hourly_cost c
  ON q.warehouse_id = c.warehouse_id
  AND q.query_hour = c.usage_hour
ORDER BY estimated_cost_usd DESC
LIMIT 50

 

Important caveats:

  1. This is an estimate, not exact billing. Warehouse DBUs include idle time, cluster startup, and shared overhead that can't be attributed to any single query.
  2. Pro/Classic warehouses bill based on cluster uptime (not per-query), so a lightweight query running alone on an idle warehouse "absorbs" the full hourly cost. Serverless SQL is closer to per-query billing but still doesn't expose it at statement granularity.
  3. total_task_duration_ms is the best available proxy because it reflects actual CPU-seconds consumed across all cores, unlike wall-clock duration which includes queueing.
  4. Retention: system.query.history retains 30 days; system.billing.usage retains 365 days.

Feature request: If exact per-query cost attribution is critical for your use case (chargeback, showback), I'd recommend filing a request on the Databricks Ideas Portal โ€” it's a frequently requested feature.

If my answer was helpful, please consider marking it as accepted solution!

AbhilashNagilla
Databricks Employee
Databricks Employee

The published system tables do not expose the exact cost of an individual SQL statement. system.billing.usage records warehouse-attributed usage for each record's time interval, but has no statement or session ID. system.query.history records statement_id, compute.warehouse_id, and timing metrics, but has no billing-record key, cost, or DBU column; warehouse ID plus overlapping time can correlate the tables, but cannot uniquely join a billing record to a statement.

For showback, you can define a heuristic that allocates each interval's warehouse cost among overlapping statements, with total_task_duration_ms as one possible weighting factor. Databricks documents that metric's meaning and the effective-date join from usage to list prices, but does not prescribe a per-query allocation formula. Concurrency, autoscaling, cache hits, shared idle time, and queries spanning intervals can skew the allocation, and published list cost can differ from invoice cost.

The system tables reference lists a 365-day free retention period for both tables.