Skip to content

Sample Snowflake query history to bound extract size (#2532)#2543

Closed
jneil17 wants to merge 2 commits into
mainfrom
feature/snowflake-profiler-query-sampling
Closed

Sample Snowflake query history to bound extract size (#2532)#2543
jneil17 wants to merge 2 commits into
mainfrom
feature/snowflake-profiler-query-sampling

Conversation

@jneil17

@jneil17 jneil17 commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Summary

query_history produced a multi-GB extract driven by QUERY_TEXT (avg ~500 chars, up to ~1M). This pull request replaces it with a random sample that always leads to a flat, predictable size.

Changes

  • query_history — now a random sample (ORDER BY RANDOM() LIMIT 10000, 90-day window) with QUERY_TEXT, for the downstream skill to classify the workload mix.
  • query_history_top (new) — top 20 queries by credits (with QUERY_TEXT) so outliers the sample misses are still captured.
  • query_history_stats (new) — full-window aggregates (no query text) by QUERY_TYPE × WAREHOUSE_SIZE: counts + total/avg/median/p90 credits & elapsed. Carries the true totals the sampled mix is applied against.
  • user_activity — per-user/client summary of LOGIN_HISTORY instead of a per-event dump (secondary bloat noted in the issue).

Notes

  • Window (90d) and sample size (10k) are currently hardcoded in SQL; making them CLI-configurable is a possible follow-up.
  • query_history_stats credits are attributed/estimated and won't perfectly reconcile with warehouse_usage (WAREHOUSE_METERING_HISTORY), which remains the billing source of truth.

Closes #2532

This pull request and its description were written by Isaac.

The full 90-day QUERY_HISTORY pull (incl. QUERY_TEXT, avg ~500 chars, up to
~1M) produced multi-GB extracts on high-volume accounts that exceeded export
limits. Replace it with a bounded set of extracts:

- query_history: random sample (<=10k rows) with QUERY_TEXT for the skill to
  classify the workload mix.
- query_history_top: top 20 queries by credits (with text) so outliers the
  sample misses are still captured.
- query_history_stats: full-window aggregates (no text) by query type and
  warehouse size, carrying the true totals the sampled mix is applied against.
- user_activity: per-user summary of LOGIN_HISTORY instead of a per-event dump.

Per-query credits use QUERY_ATTRIBUTION_HISTORY, falling back to an
execution-time x warehouse-size-rate estimate (IS_CREDITS_ESTIMATED). Workload
classification stays in the downstream skill; the profiler only delivers totals
and a representative sample.

Co-authored-by: Isaac
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@codecov

codecov Bot commented Jun 30, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 69.18%. Comparing base (db0bfbc) to head (b624992).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #2543   +/-   ##
=======================================
  Coverage   69.18%   69.18%           
=======================================
  Files         105      105           
  Lines        9503     9503           
  Branches     1052     1052           
=======================================
  Hits         6575     6575           
  Misses       2731     2731           
  Partials      197      197           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions

github-actions Bot commented Jun 30, 2026

Copy link
Copy Markdown

✅ 169/169 passed, 8 flaky, 2 skipped, 45m22s total

Flaky tests:

  • 🤪 test_installs_and_runs_local_bladebridge (12.835s)
  • 🤪 test_installs_and_runs_pypi_bladebridge (22.701s)
  • 🤪 test_transpiles_informatica_to_sparksql_non_interactive[True] (23.854s)
  • 🤪 test_transpiles_informatica_to_sparksql_non_interactive[False] (24.262s)
  • 🤪 test_transpiles_informatica_to_sparksql (25.597s)
  • 🤪 test_transpile_teradata_sql_non_interactive[True] (6.541s)
  • 🤪 test_transpile_teradata_sql_non_interactive[False] (6.6s)
  • 🤪 test_transpile_teradata_sql (7.407s)

Running from acceptance #4962

Drop the user_activity step entirely rather than summarizing it. The login
history it captured isn't used in the TCO analysis, so removing it trims the
extract further and keeps the profiler focused on cost-relevant data.

Co-authored-by: Isaac

@dgomez04 dgomez04 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The core issue is fixed but grows execution time significantly. Let's look into this deeper before approving.

-- Extract query execution patterns, performance metrics, and user activity
-- Query History — bounded RANDOM sample for workload classification
--
-- Issue #2532: the previous step pulled the full 90-day QUERY_HISTORY including

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We don't need to mention the issue within the comment, we should make it flatter and straight to the point.

frequency: daily
flag: active

# Bounded RANDOM sample of query history (incl. QUERY_TEXT) for workload

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Remove this comment.

flag: active

- name: storage_usage
# Top-N most expensive queries (with QUERY_TEXT) so the random sample never

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Remove this comment.

flag: active

- name: user_activity
# Full-window aggregate (no query text): true totals + per-group distribution

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Remove this comment.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The pull request description mentions that user_activity still exists but here it's completely removed. Can we confirm whether this is the intended behavior?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Each of the new pipeline steps scans the full 90-day QUERY_HISTORY window independently. Export size is fixed, but the total execution time can grow by ~3x compared to the old, single-step run.

I believe this is something we should look into further.

FROM SNOWFLAKE.ACCOUNT_USAGE.QUERY_HISTORY qh
LEFT JOIN attributed a ON qh.QUERY_ID = a.QUERY_ID
WHERE qh.START_TIME >= DATEADD('day', -90, CURRENT_TIMESTAMP())
ORDER BY RANDOM()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ORDER BY RANDOM() LIMIT 10000 may still require Snowflake to touch every row before applying the limit.

Has execution time been benchmarked?

Did we consider other alternatives such as SAMPLE (10000 ROWS) or hash-based sampling like (MOD(ABS(HASH(QUERY_ID)), …))? They could be much cheaper while still giving a representative mix.

Additionally, is there any reason for us to get 90 days of history rather than 30?

@dgomez04

Copy link
Copy Markdown
Contributor

Closing off as I'll be reworking based on some new insights.

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.

[ISSUE]: Snowflake profiler extract is too large on high-volume accounts

3 participants