What you will be able to do
- Find the longest-running queries on a specific warehouse using Snowsight Query History filters and sorting
- Choose between Snowsight, the Information Schema QUERY_HISTORY table functions and the ACCOUNT_USAGE QUERY_HISTORY view based on retention, latency and access
- Use query_hash and query_parameterized_hash to tell a consistently slow query pattern apart from a one-off outlier
- Read the QUERY_HISTORY timing, queueing, spill and pruning columns to decide where a query's time actually went
- Outline the telemetry available around a slow operation (statement, operator, insight, warehouse and task level) and pick the right source for each question
Key concept
Statement-level vs operator-level telemetry — Query History tells you which statements are slow and gives totals for each one: elapsed time, queueing, bytes scanned, spill. The Query Profile goes one level down and shows which operator inside a single statement used up that time. Troubleshooting moves from the first to the second.
1.Start with Snowsight Query History
Before you can fix a slow query, you have to find it. People often blame a warehouse when one or two statements are really the problem, so the first job is to rank queries by how long they took. In Snowsight, go to Monitoring » Query History. The Duration column shows how long each statement took to execute. Sort on it and the longest-running queries come to the top.
On a busy account the full list is noisy, so filter it. The User drop-down limits the list to one person's queries. Filters » Warehouse limits it to one warehouse, which is what you want when one warehouse seems to be slowing down. You can also filter by Status (for example to find long-running, failed or queued queries), Statement Type, SQL Text, Query Tag, Session ID and Duration. The page covers the last 14 days. You can add optional columns such as Warehouse Size, Bytes Scanned and Rows, which give a first clue about whether a slow query was simply reading a lot of data.
What you can see depends on your role. You can always see your own queries. ACCOUNTADMIN sees all query history for the account. A role with MONITOR or OPERATE on a warehouse can see other users' queries on that warehouse. Two practical details: details for queries more than seven days old do not include User information, and once more results are loaded the table can no longer be sorted. If you sort and then select Load More, the new rows are appended at the end and the sort order no longer applies.
Checkpoint 1 of 6· Check yourself
An engineer's role has the OPERATE privilege on warehouse ETL_WH, but no other monitoring grants. In Snowsight Query History, whose queries can they see?
Everyone can see their own history. MONITOR or OPERATE on a warehouse also shows other users' queries on that warehouse. Seeing the whole account requires ACCOUNTADMIN.
“you can view queries run by other users that use that warehouse”Source: docs.snowflake.com
Checkpoint 2 of 6· Exam question
A data engineer opens the Query Profile for a report query that took 40 seconds and wants to focus tuning effort where it will matter most. Which panel should they check first to find which operators consumed the largest share of execution time?
Correct answer: A — The Most Expensive Nodes pane, which lists operators using 1% or more of total execution time ranked by duration so effort targets the biggest contributors first
- A. Correct: the Most Expensive Nodes pane in Query Profile ranks operators consuming a meaningful share of execution time in descending order, which is exactly the view built for prioritizing which node to investigate first.
- B. Incorrect: the formatted query text panel helps read the SQL that was submitted, but it does not map elapsed time onto operators, so it cannot show where time was actually spent during execution.
- C. Incorrect: a credit usage chart tracks warehouse-level billing over a time window and says nothing about how one specific query's execution time was distributed across its plan operators.
- D. Incorrect: an account-wide Query History summary rolls up many queries and warehouses together, so it cannot isolate the operator-level time breakdown for this single 40-second query.
2.Going beyond 14 days: QUERY_HISTORY in SQL
Snowsight is good for looking around. For repeatable reports, trends or anything older than two weeks, query the history with SQL. There are two places to do that, and they differ in ways the exam tests. The ACCOUNT_USAGE.QUERY_HISTORY view keeps a year of history but has a delay. The Information Schema QUERY_HISTORY table functions are updated faster but only cover the past 7 days. By default, ACCOUNT_USAGE is visible only to ACCOUNTADMIN. Users without that access, such as the person who ran the query or a warehouse administrator, can still use the Information Schema functions.
| Source | History covered | Freshness / access notes |
|---|---|---|
| Snowsight Query History page | Last 14 days | Best for checking a query right after it runs |
| INFORMATION_SCHEMA QUERY_HISTORY table functions | Past 7 days | Updated faster than ACCOUNT_USAGE; available to users without ACCOUNT_USAGE access |
| SNOWFLAKE.ACCOUNT_USAGE.QUERY_HISTORY view | Last 365 days | Latency up to 45 minutes; ACCOUNTADMIN by default |
The documentation's starting query lists the 50 longest-running successful queries on one warehouse over the last day. It also returns partitions_scanned next to partitions_total, so a long runtime can be compared against how much of the table was read. Widen the DATEADD window to look at a longer period.
SELECT query_id,
ROW_NUMBER() OVER(ORDER BY partitions_scanned DESC) AS query_id_int,
query_text,
total_elapsed_time/1000 AS query_execution_time_seconds,
partitions_scanned,
partitions_total,
FROM snowflake.account_usage.query_history Q
WHERE warehouse_name = 'my_warehouse' AND TO_DATE(Q.start_time) > DATEADD(day,-1,TO_DATE(CURRENT_TIMESTAMP()))
AND total_elapsed_time > 0 --only get queries that actually used compute
AND error_code IS NULL
AND partitions_scanned IS NOT NULL
ORDER BY total_elapsed_time desc
LIMIT 50;Checkpoint 3 of 6· Check yourself
A developer runs a query, then immediately queries SNOWFLAKE.ACCOUNT_USAGE.QUERY_HISTORY for its elapsed time. The row isn't there. What is the best explanation and next step?
QUERY_HISTORY in ACCOUNT_USAGE can lag by up to 45 minutes. Snowsight and the Information Schema are updated faster, so use them to check a query that just ran.
“If you want to check the execution time of a query right after running it, use Snowsight to view its performance.”Source: docs.snowflake.com
QUERY_HISTORY is one layer of the telemetry that surrounds a slow operation. Before choosing a fix, outline what each layer can tell you. The statement layer (QUERY_HISTORY in Snowsight, ACCOUNT_USAGE or the Information Schema) gives per-query totals: elapsed, compilation and execution time, queueing, bytes scanned, spill and partitions scanned. The operator layer is the Query Profile, opened from a query ID in Query History. Its Most Expensive Nodes pane shows which operators ran longest, and you can run GET_QUERY_OPERATOR_STATS to get the same statistics in SQL. The insight layer flags conditions that affect performance, such as a join with no join condition or remote spillage. The warehouse layer (the Warehouse Activity chart and WAREHOUSE_LOAD_HISTORY) shows whether queries were queued by load. The task layer (TASK_HISTORY) shows how long scheduled runs took. Work from the wide view to the narrow one: find the statement, check whether the time was waiting or work, then drill into the operators.
| Level | Where to look | Question it answers |
|---|---|---|
| Statement | QUERY_HISTORY (Snowsight, ACCOUNT_USAGE view or Information Schema table function) | Which statements are slow, and how much was elapsed, queued, scanned or spilled? |
| Operator | Query Profile; GET_QUERY_OPERATOR_STATS | Which operator inside the statement used the time, and how is it split in EXECUTION_TIME_BREAKDOWN? |
| Insight | Query Insights pane; QUERY_INSIGHTS view | Which known condition (for example a join with no join condition) is hurting this query? |
| Warehouse | Warehouse Activity chart; WAREHOUSE_LOAD_HISTORY | Was the warehouse loaded so that queries queued? |
| Task | TASK_HISTORY | Which scheduled task runs take longest? |
3.Consistently slow or a one-off? Query hashes
A single slow run tells you little. The same statement might have run fine a hundred times and slowed down once because of contention. Or a query that takes three seconds might run ten thousand times a day and cost more than any big report. To see either case you need to group runs of the same query together, and QUERY_HISTORY provides two keys for this:
- query_hash is computed from the canonicalized SQL text, so identical statements share it. - query_parameterized_hash is computed from the parameterized query, so statements that differ only in literal values (for example, a different user ID) share it.
Grouping by query_hash and summing elapsed time puts the most expensive statements first, counting every run, which is often a better place to start optimizing than the single slowest run.
SELECT
query_hash,
COUNT(*),
SUM(total_elapsed_time),
ANY_VALUE(query_id)
FROM SNOWFLAKE.ACCOUNT_USAGE.QUERY_HISTORY
WHERE warehouse_name = 'MY_WAREHOUSE'
AND DATE_TRUNC('day', start_time) >= CURRENT_DATE() - 7
GROUP BY query_hash
ORDER BY SUM(total_elapsed_time) DESC
LIMIT 100;To check whether one pattern has drifted, track its daily average elapsed time over a month. A flat line with one spike points to an outlier. A steady rise points to a lasting regression, such as data growth or a plan change. Snowsight shows the same view graphically: Monitoring » Query History » Grouped Queries groups executions by parameterized query hash and shows run count, failures, p50/p90/p99 latency and executions per minute. It is based on the AGGREGATE_QUERY_HISTORY view, so new queries can take up to three hours to appear.
Checkpoint 4 of 6· Fill the gap
This query computes the daily average elapsed time for every execution of one query pattern, even when the literal values differ between runs. Which column belongs in the blank?
SELECT
DATE_TRUNC('day', start_time),
AVG(total_elapsed_time),
ANY_VALUE(query_id)
FROM SNOWFLAKE.ACCOUNT_USAGE.QUERY_HISTORY
WHERE ? = 'cbd58379a88c37ed6cc0ecfebb053b03'
AND DATE_TRUNC('day', start_time) >= CURRENT_DATE() - 30
GROUP BY DATE_TRUNC('day', start_time);query_parameterized_hash is the same for every run of a parameterized statement, so averaging over it tracks how one pattern performs over time. A query_id identifies only one execution.
Source: docs.snowflake.comCheckpoint 5 of 6· Exam question
A nightly transformation query is taking far longer than usual, and the Query Profile Statistics pane shows a large value for 'Bytes spilled to local storage' with none spilled to remote storage. What does this indicate, and what is the most direct fix?
Correct answer: A — An operator's intermediate result exceeded the memory available on the warehouse, so increasing the warehouse size to give each node more memory should reduce the spilling
- A. Correct: spilling to local storage means an operator's working set, such as a large sort or hash join build side, did not fit in the memory available to the warehouse, and sizing up gives the query more memory per node.
- B. Incorrect: poor pruning shows up in the TableScan operator's partition scan ratio, not as spilled bytes, and a clustering key addresses how many partitions are read, not how much memory an operator needs.
- C. Incorrect: a cold warehouse resume affects the first query's startup latency and cache state, but it does not produce a nonzero spilled-bytes metric, which is specifically a memory-pressure indicator during execution.
- D. Incorrect: hitting a concurrency limit produces queued queries with wait time before execution starts, which is a separate telemetry signal from spilled bytes recorded once a query is running.
Sources2
4.Reading where the time went
total_elapsed_time is only the headline figure. QUERY_HISTORY splits it into parts, and each part points to a different kind of cause. Some columns describe *waiting* (a warehouse problem or a concurrency problem). Others describe *work* (a query or data-layout problem). Look at these columns before you rewrite any SQL.
| Column | What it measures | What a large value suggests |
|---|---|---|
| compilation_time | Compilation time (ms) | Time spent before execution started |
| queued_provisioning_time | Queue time waiting for compute to provision due to warehouse creation, resume, or resize | The warehouse was starting or resizing, not that the SQL is slow |
| queued_overload_time | Queue time because the warehouse was overloaded by current workload | Concurrency pressure on the warehouse |
| transaction_blocked_time | Time blocked by a concurrent DML | Lock contention, not query design |
| bytes_spilled_to_local_storage / bytes_spilled_to_remote_storage | Volume of data spilled to local or remote disk | Intermediate results did not fit in memory |
| partitions_scanned vs partitions_total | Micro-partitions scanned vs total in the tables queried | Scanned close to total means pruning had little effect |
| percentage_scanned_from_cache | Share of data scanned from the local disk cache (0.0–1.0) | How much of the scan was served from the warehouse cache |
For queueing, also check the warehouse as a whole. In Snowsight, Compute » Warehouses has a Warehouse Activity chart that shows load and whether queries were queued. In SQL, WAREHOUSE_LOAD_HISTORY (latency up to 3 hours) reports load as a ratio. For example, 276 seconds of query time in a 300-second interval gives a load of 0.92. The query below finds the days on which a warehouse had queued load. For pipelines, TASK_HISTORY gives the same kind of view for tasks: sorting successful runs by duration shows which task SQL is worth optimizing. Snowsight shows task timings under Transformation » Tasks.
SELECT TO_DATE(start_time) AS date,
warehouse_name,
SUM(avg_running) AS sum_running,
SUM(avg_queued_load) AS sum_queued
FROM snowflake.account_usage.warehouse_load_history
WHERE TO_DATE(start_time) >= DATEADD(month,-1,CURRENT_TIMESTAMP())
GROUP BY 1,2
HAVING SUM(avg_queued_load) >0;Checkpoint 6 of 6· Check yourself
A scheduled query on a warehouse that had just been suspended shows a large queued_provisioning_time and a normal execution_time. What should the engineer conclude first?
queued_provisioning_time measures waiting for warehouse compute during creation, resume or resize. With execution_time unchanged, the SQL itself is not the problem.
“spent in the warehouse queue, waiting for the warehouse compute resources to provision, due to warehouse creation, resume, or resize”Source: docs.snowflake.com
Sources1
Exam traps
Each one states something that sounds right. Open it to see what is actually true.
1.The Information Schema QUERY_HISTORY table function returns the same year of history as the ACCOUNT_USAGE view, only faster.Why is that wrong?
The table function covers only the past 7 days. The ACCOUNT_USAGE view keeps 365 days but can lag by up to 45 minutes.
Covered in Going beyond 14 days: QUERY_HISTORY in SQL
2.After sorting Query History by Duration and selecting Load More, the full list is still in duration order.Why is that wrong?
Once more results are loaded the table can't be sorted. New rows are appended at the end and the earlier sort no longer applies.
Covered in Start with Snowsight Query History
3.The query to optimize first is always the one with the longest single run.Why is that wrong?
A cheap query that runs very often can cost more in total. Grouping by query hash and summing elapsed time shows this.
Covered in Consistently slow or a one-off? Query hashes
Sources
Every claim above is drawn from one of these pages, quoted as it was written on the date shown.
- 1.
“Use the Duration column to understand how long it took a query to execute.”
↩︎ Start with Snowsight Query History“By default, only the account administrator (i.e. user with the ACCOUNTADMIN role) can access views in the ACCOUNT_USAGE schema.”
↩︎ Going beyond 14 days: QUERY_HISTORY in SQL“The Information Schema is also updated quicker than the ACCOUNT_USAGE views.”
↩︎ Going beyond 14 days: QUERY_HISTORY in SQL“You can programmatically access the performance statistics of the Query Profile by executing the GET_QUERY_OPERATOR_STATS function.”
↩︎ Going beyond 14 days: QUERY_HISTORY in SQL“Use the Warehouse Activity chart to visualize the load of the warehouse, including whether queries were queued.”
↩︎ Reading where the time went“which can indicate an opportunity to optimize the SQL being executed by the task”
↩︎ Reading where the time went“The Query Profile allows you to examine which parts of a query are taking the longest to execute.”
↩︎ Key concept“a frequently repeated query could lead to high costs, based on the number of times the query runs.”
↩︎ Exam trap 3“If you want to check the execution time of a query right after running it, use Snowsight to view its performance.”
↩︎ Checkpoint - 2.
“The Query History page lets you explore queries executed in your Snowflake account over the last 14 days.”
↩︎ Start with Snowsight Query History“Executed queries are grouped by a parameterized query hash ID.”
↩︎ Consistently slow or a one-off? Query hashes“Snowsight displays the total number of queries executed, the number of queries that failed, latency (p50, p90, p99), and executions per minute.”
↩︎ Consistently slow or a one-off? Query hashes“If you have more results, you cannot sort the table.”
↩︎ Exam trap 2“you can view queries run by other users that use that warehouse”
↩︎ Checkpoint - 3.
“You can access these insights in Snowsight and by querying the QUERY_INSIGHTS view.”
↩︎ Going beyond 14 days: QUERY_HISTORY in SQL
Also cited
“the table function restricts the results to activity over the past 7 days, versus 365 days for the Account Usage view”
↩︎ Exam trap 1“Time (in milliseconds) spent in the warehouse queue, due to the warehouse being overloaded by the current query workload.”
↩︎ Prediction“spent in the warehouse queue, waiting for the warehouse compute resources to provision, due to warehouse creation, resume, or resize”
↩︎ Checkpoint