CertSafari
    Snowflake SnowPro Advanced: Data Engineer (DEA-C02)· Lessons

    Domain 2 · Lesson 8/22

    Finding Slow Snowflake Queries with Query History Telemetry

    Troubleshoot underperforming queries.

    13 min read
    6.33% of exam
    4 sources
    Published 5 Oct 2026
    Docs as of 4 Oct 2026

    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?

    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?

    Sources12

    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.

    Where to find query history, and the trade-offs of each
    SourceHistory coveredFreshness / access notes
    Snowsight Query History pageLast 14 daysBest for checking a query right after it runs
    INFORMATION_SCHEMA QUERY_HISTORY table functionsPast 7 daysUpdated faster than ACCOUNT_USAGE; available to users without ACCOUNT_USAGE access
    SNOWFLAKE.ACCOUNT_USAGE.QUERY_HISTORY viewLast 365 daysLatency 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.

    Top 50 longest-running queries on one warehouse in the last day, with pruning statisticssql
    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 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.

    Telemetry around one slow operation, from wide to narrow
    LevelWhere to lookQuestion it answers
    StatementQUERY_HISTORY (Snowsight, ACCOUNT_USAGE view or Information Schema table function)Which statements are slow, and how much was elapsed, queued, scanned or spilled?
    OperatorQuery Profile; GET_QUERY_OPERATOR_STATSWhich operator inside the statement used the time, and how is it split in EXECUTION_TIME_BREAKDOWN?
    InsightQuery Insights pane; QUERY_INSIGHTS viewWhich known condition (for example a join with no join condition) is hurting this query?
    WarehouseWarehouse Activity chart; WAREHOUSE_LOAD_HISTORYWas the warehouse loaded so that queries queued?
    TaskTASK_HISTORYWhich scheduled task runs take longest?

    Sources13

    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.

    Rank query patterns on a warehouse by total elapsed time over the last 7 dayssql
    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);

    Checkpoint 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?

    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.

    QUERY_HISTORY columns that locate the bottleneck
    ColumnWhat it measuresWhat a large value suggests
    compilation_timeCompilation time (ms)Time spent before execution started
    queued_provisioning_timeQueue time waiting for compute to provision due to warehouse creation, resume, or resizeThe warehouse was starting or resizing, not that the SQL is slow
    queued_overload_timeQueue time because the warehouse was overloaded by current workloadConcurrency pressure on the warehouse
    transaction_blocked_timeTime blocked by a concurrent DMLLock contention, not query design
    bytes_spilled_to_local_storage / bytes_spilled_to_remote_storageVolume of data spilled to local or remote diskIntermediate results did not fit in memory
    partitions_scanned vs partitions_totalMicro-partitions scanned vs total in the tables queriedScanned close to total means pruning had little effect
    percentage_scanned_from_cacheShare 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.

    Days in the last month when each warehouse had queued loadsql
    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?

    Sources1

    Exam traps

    Each one states something that sounds right. Open it to see what is actually true.

    1. 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. 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. 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. 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. 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. 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

    Continue to page 2 of 2

    Query Profile and Query Insights: Root-Causing and Fixing Slow Queries

    Spotted a mistake, or was something unclear? Tell us.