What you will be able to do
- Read a Query Profile: steps, the operator tree, operator nodes and the common operator types
- Use EXPLAIN to see the planned operations of a statement before it runs, and compare that with the runtime statistics in the Query Profile
- Spot exploding joins and unnecessary UNION duplicate elimination from operator row counts
- Diagnose data spilling and poor micro-partition pruning, and choose the documented fixes
- Use STATEMENT_TIMEOUT_IN_SECONDS to cancel runaway statements
- Articulate the execution path of a query by reading an EXPLAIN plan from the TableScan leaves up through parentOperators to Result
- Troubleshoot common query performance issues with query insights and GET_QUERY_OPERATOR_STATS, and match each insight to its documented fix
- Compare and contrast the result cache, the warehouse (local disk) cache and metadata-based results, and their impact on performance
- Explain what happens to the warehouse cache when a warehouse is suspended or resumed, and choose an auto-suspend setting for a workload
Key concept
Operator node — A query plan is a tree of operators such as TableScan, Join, Aggregate and Result. Each operator is a node in the Query Profile with its own time and row statistics. Tuning starts with finding the node that costs the most and asking why.
1.Anatomy of a Query Profile: steps, tree, nodes and operator types
Query history tells you which queries are slow. The Query Profile tells you why. To open it in Snowsight, go to Monitoring » Query History, select a query ID, and then select the Query Profile tab. The profile shows the query as a tree of operators. In that tree a parent operator sits above its child, with a link between them, and rows flow upward from the scans at the bottom to the Result at the top. Most queries run as a single step. Some are executed as several distinct steps, and each step has its own operator tree.
Each box in the tree is an operator node. The Most Expensive Nodes pane lists the nodes that take the longest to execute. For each node you can see what percentage of its time went to each category of processing. To get the same statistics in SQL instead of the UI, call the GET_QUERY_OPERATOR_STATS function.
| Operator type | What it represents |
|---|---|
| TableScan | Access to a single table, with attributes such as the scanned columns and access predicates |
| ExternalScan | Access to data stored in stage objects, including COPY loads |
| IndexScan | Access to secondary indexes on hybrid tables |
| Filter | An operation that filters the records, with a filter condition |
| Join | Combines two inputs on a join condition |
| JoinFilter | Removes tuples that cannot possibly match the condition of a Join further in the plan |
| Aggregate | Grouping (GROUP BY) and SELECT DISTINCT, and also the duplicate elimination added by UNION |
| GroupingSets | Constructs such as GROUPING SETS, ROLLUP and CUBE |
| WindowFunction | Computes window functions |
| Sort | Orders its input on a sort-key expression |
| SortWithLimit | A part of the sorted input, typically from ORDER BY ... LIMIT ... OFFSET ... |
| Flatten | Processes VARIANT records, possibly flattening them on a path |
| UnionAll | Concatenates its inputs |
| Generator / ValuesClause | Rows produced by TABLE(GENERATOR(...)) or a VALUES list |
| Result | Returns the query result |
Checkpoint 1 of 8· Put it in order
Put the steps for opening a query's Query Profile in Snowsight in order
- 1.Select the query ID of a query
- 2.In the navigation menu, select Monitoring » Query History
- 3.Select the Query Profile tab
- 4.Sign in to Snowsight
You reach the profile through Query History. You pick the query first, and then open its Query Profile tab.
“In the navigation menu, select Monitoring » Query History.”Source: docs.snowflake.com
Checkpoint 2 of 8· Exam question
A nightly aggregation on a MEDIUM warehouse joins a 4 TB fact table to a large dimension table and runs for hours. The Query Profile shows 'Bytes spilled to remote storage' in the Join and Aggregate operators and very high Remote Disk IO time. Which action is the MOST appropriate first step?
Correct answer: A — Run the query on a larger warehouse so each node has more memory and local disk for intermediate join result data
- A. Correct. Remote spilling means intermediate results exceeded both memory and local SSD, so a larger warehouse (more memory and local disk per query) or reducing the data processed by filtering earlier removes the spill.
- B. Incorrect. Search optimization accelerates selective point lookups and does not reduce the memory needed by a large join or aggregation, so spilling continues.
- C. Incorrect. A statement timeout only cancels long-running statements; it does nothing to give the join more memory and simply makes the nightly job fail.
- D. Incorrect. Multi-cluster warehouses add clusters for concurrency, but a single query still runs on one cluster, so its memory shortage and spilling remain.
2.EXPLAIN: the plan before it runs, and how to articulate the execution path
The Query Profile describes a query that has already run. EXPLAIN works on a statement before it runs. It returns the logical execution plan, meaning the operations Snowflake would perform, such as table scans and joins. You get it without paying to run the query. The output can be TABULAR (the default), JSON or TEXT. JSON is the easiest format to store in a table and query.
EXPLAIN [ USING { TABULAR | JSON | TEXT } ] <statement>| Column | Meaning |
|---|---|
| step | Which step the operation belongs to; most queries have one |
| id | Unique identifier of the operation in the plan |
| parentOperators | Identifiers of parent nodes; the profile draws a parent above its child |
| operation | Operator name, for example Result, Filter, TableScan or Join |
| objects | Object a table scan reads, for example a table or materialized view |
| expressions | Filters, join conditions and other expressions for the operation |
To articulate the execution path of a query, read the plan from the bottom up. The leaves are scan operators such as TableScan. They sit at the bottom of the tree and are the first step in reading the data the query needs. Each row of the plan names its parent in parentOperators, so you can follow every branch upward until it reaches the Result operator at id 0. Take the documented plan for SELECT Z1.ID, Z2.ID FROM Z1, Z2 WHERE Z2.ID = Z1.ID, shown below. Z2 is scanned (id 2) and feeds the InnerJoin directly. Z1 is scanned (id 4) and passes through a JoinFilter (id 3) first, which removes rows that cannot match the join. Both branches meet at the InnerJoin (id 1) on joinKey (Z2.ID = Z1.ID), and the InnerJoin feeds Result (id 0).
| id | parentOperators | operation | objects / expressions |
|---|---|---|---|
| 0 | NULL | Result | Z1.ID, Z2.ID |
| 1 | [0] | InnerJoin | joinKey: (Z2.ID = Z1.ID) |
| 2 | [1] | TableScan | TESTDB.TEMPORARY_DOC_TEST.Z2 |
| 3 | [1] | JoinFilter | joinKey: (Z2.ID = Z1.ID) |
| 4 | [3] | TableScan | TESTDB.TEMPORARY_DOC_TEST.Z1 |
Be precise about what this path means. The EXPLAIN plan is the logical plan. It shows which operations will be performed and how they relate to each other. The actual execution order does not necessarily match the logical order the plan shows.
That difference is also the line between compile-time and runtime optimization. EXPLAIN compiles the statement but does not execute it, so it needs no running warehouse. The compiler does use Cloud Services credits. The plan records compile-time decisions: the operator tree, the join expressions, the objects to scan, and partitionsAssigned, which is the number of partitions left after compile-time pruning. The partitionsAssigned and bytesAssigned values are upper-bound estimates. At runtime, optimizations such as join pruning can reduce the partitions and bytes actually scanned. The plan can also differ with the size of the current warehouse. The Query Profile then adds what actually happened at runtime: time per node, rows produced, spilling and partitions scanned. Spilling and real pruning effectiveness appear only in that runtime view.
Checkpoint 3 of 8· Check yourself
You run EXPLAIN on a query without a USING clause. What format is the plan returned in?
TABULAR is the default output format. You get JSON or TEXT only if you ask for it with USING.
“The default is TABULAR.”Source: docs.snowflake.com
3.Troubleshoot common query performance issues: joins, unions and grouping
Two common query-writing mistakes are easy to see in the profile. The first is a bad join condition. Joining without a condition produces a Cartesian product. A condition where one row matches many rows on the other side does something similar. In both cases the Join operator outputs far more rows than it takes in, often by orders of magnitude, and it usually takes a lot of time as well. Compare the rows going into the Join node with the rows coming out of it.
The second mistake is using UNION when UNION ALL would give the right answer. UNION ALL just concatenates its inputs. UNION also removes duplicates. In the profile this shows as a UnionAll operator with an extra Aggregate operator on top. If duplicates cannot occur, or do not matter, that Aggregate is wasted work.
Grouping, sorting and ordering each show up as their own operators, so you can see what they cost. GROUP BY and SELECT DISTINCT appear as an Aggregate node, GROUPING SETS, ROLLUP and CUBE as GroupingSets, window functions as WindowFunction, ORDER BY as Sort, and ORDER BY ... LIMIT as SortWithLimit. A DISTINCT or GROUP BY that returns the same number of rows as the query without it adds a processing step with no effect on the result, so remove it. When a GROUP BY is on a high-cardinality expression, the query acceleration service may not be able to help the query. For repeated range searches or sort operations, materialized views are a documented option. For "most recent N rows" queries (ORDER BY plus LIMIT) on interactive warehouses, the documentation advises making the clustering key match the ORDER BY column so pruning works.
To troubleshoot common query performance issues, follow a fixed routine. Open the Query Profile and check the Query Insights pane. Snowflake highlights the nodes that have insights, and selecting View on an entry shows the condition it detected and the recommended next steps. The same insights are in the SNOWFLAKE.ACCOUNT_USAGE.QUERY_INSIGHTS view, one row per insight, with a latency of up to 90 minutes. Insights are not produced for every query. EXPLAIN queries, queries that reuse results, multi-step queries and queries against hybrid tables do not get them.
Use effective joining conditions. A join with no condition becomes a cross join that returns every possible combination of rows. A complex join condition that can only be evaluated after the join is less efficient than one evaluated before it. Non-equality join predicates can be significantly slower and should be avoided if possible. To find an exploding join in SQL, divide each Join operator's output_rows by its input_rows with GET_QUERY_OPERATOR_STATS, and then check the join condition of any operator with a large ratio.
SELECT operator_id,
operator_attributes,
operator_statistics:output_rows / operator_statistics:input_rows AS row_multiple
FROM TABLE(GET_QUERY_OPERATOR_STATS($lid))
WHERE operator_type = 'Join'
ORDER BY step_id, operator_id;| Insight type ID | What it means | Documented fix |
|---|---|---|
| QUERY_INSIGHT_JOIN_WITH_NO_JOIN_CONDITION | The join has no condition and becomes a cross join | Specify one or more join conditions |
| QUERY_INSIGHT_EXPLODING_JOIN | A join returns many more rows than the joined tables contain | Add or change the join condition; a WHERE clause in a subquery can reduce rows |
| QUERY_INSIGHT_INEFFICIENT_JOIN_CONDITION | A complex join condition is evaluated after the data sets are joined | Simplify the join condition |
| QUERY_INSIGHT_INEFFICIENT_AGGREGATE | DISTINCT or GROUP BY returns the same number of rows as without it | Remove the unnecessary DISTINCT or GROUP BY |
| QUERY_INSIGHT_UNNECESSARY_UNION_DISTINCT | UNION removes duplicates from input sets that are disjoint | Use UNION ALL |
| QUERY_INSIGHT_LIKE_WITH_LEADING_WILDCARD | A LIKE pattern starts with a wildcard and scans a lot of data | Avoid the leading wildcard, or consider search optimization |
| QUERY_INSIGHT_REMOTE_SPILLAGE | The warehouse spilled data to storage | Use a larger warehouse, or process data in smaller batches |
| QUERY_INSIGHT_QUEUED_OVERLOAD | The query waited in the warehouse queue too long | Use a larger warehouse, or one with fewer concurrent queries |
Checkpoint 4 of 8· Check yourself
A profile shows a UnionAll operator with an Aggregate operator directly above it. The two inputs can never share rows. What is the most likely fix?
The extra Aggregate is UNION's duplicate elimination. If duplicates are impossible, UNION ALL returns the same rows without that operator.
“These queries show in Query Profile as a UnionAll operator with an extra Aggregate operator on top (which performs duplicate elimination).”Source: docs.snowflake.com
4.Data spilling and caching: impact and solutions
Performance drops sharply when a warehouse runs out of memory during a query. Data that no longer fits in memory spills to local disk, and if that runs out too, it spills to remote storage. Spilling to remote storage does the most damage. The Query Profile shows which operator nodes are spilling. To find the worst offenders across the account, query QUERY_HISTORY:
SELECT query_id, SUBSTR(query_text, 1, 50) partial_query_text, user_name, warehouse_name,
bytes_spilled_to_local_storage, bytes_spilled_to_remote_storage
FROM snowflake.account_usage.query_history
WHERE (bytes_spilled_to_local_storage > 0
OR bytes_spilled_to_remote_storage > 0 )
AND start_time::date > dateadd('days', -45, current_date)
ORDER BY bytes_spilled_to_remote_storage, bytes_spilled_to_local_storage DESC
LIMIT 10;Snowflake recommends two fixes. One is a larger warehouse, which gives the operation more memory and local storage. The other is processing the data in smaller batches. Be careful with one false alarm: when the query acceleration service is enabled, Snowflake writes a small amount of data to remote storage for every eligible query. On those warehouses, a nonzero bytes_spilled_to_remote_storage value does not by itself mean a memory problem.
Checkpoint 5 of 8· Check yourself
A nightly transformation spills heavily to remote storage. Which action is a Snowflake-recommended remedy?
Snowflake documents two remedies: a larger warehouse, or processing the data in smaller batches. The other options do not reduce the memory the operation needs.
“Processing data in smaller batches.”Source: docs.snowflake.com
Spilling happens on the warehouse's local disk, and that disk also holds a cache. To compare and contrast the caching techniques Snowflake uses, ask three questions about each one: what is reused, what invalidates it, and what it costs. Each has a different impact on performance.
The result cache (persisted query results) has the biggest effect. If a user repeats a query and the underlying data has not changed, Snowflake does not run the query again. It returns the stored result, so execution is skipped entirely. Reuse requires that the new query matches the previous one exactly. Any difference in syntax, including lowercase versus uppercase keywords or a table alias, prevents full reuse. It also requires that the query uses no non-reusable functions such as RANDOM or UUID_STRING, uses no external functions, and does not select from hybrid tables. The table data and micro-partitions must not have changed, and the role must have the required privileges. A result expires after 24 hours. Each reuse resets that period, up to a maximum of 31 days from the query's first run. Result reuse is on by default and is controlled by the USE_CACHED_RESULT parameter. In the Query Profile, a reused result shows as Query Result Reuse.
The warehouse cache, the local disk cache (the exam guide spells it "local disc"), sits one level lower. A running warehouse keeps a cache of table data that later queries on the same warehouse can read instead of reading from the tables. This helps frequent, similar queries even when the result itself cannot be reused. The percentage_scanned_from_cache statistic, which also appears on a TableScan in GET_QUERY_OPERATOR_STATS, shows how much of a scan came from this cache.
The third kind of reuse is metadata-based results. Some queries, such as SELECT COUNT(*) FROM a table, are computed purely from metadata without accessing any data, and are not processed by a virtual warehouse at all. Materialized views are related but different: they are more flexible than cached results but typically slower.
| Mechanism | What is reused | What ends it | How to see or control it |
|---|---|---|---|
| Result cache (persisted query results) | The complete result of an identical earlier query | Expires after 24 hours (reset on reuse, up to 31 days); changed table data or micro-partitions; any syntax difference | Query Result Reuse in the Query Profile; USE_CACHED_RESULT |
| Warehouse cache (local disk) | Table data already read by queries on the same running warehouse | Dropped when the warehouse is suspended | percentage_scanned_from_cache; AUTO_SUSPEND |
| Metadata-based Result | Micro-partition metadata, without accessing any data | Not applicable: computed from metadata, not processed by a virtual warehouse | Metadata-based Result in the Query Profile, for example SELECT COUNT(*) |
Suspending or resuming a warehouse affects the local disk cache directly. When a warehouse is suspended, its cache is dropped. When it is resumed, it starts with a cold cache, and the first queries read from table storage again until the cache is rebuilt. Interactive warehouses document the same pattern: when a warehouse was suspended between bursts and resumed, the first queries show higher remote reads while cache warming finishes. So the auto-suspend setting has a direct impact on query performance. Snowflake's guidelines are immediate suspension for tasks, about 5 minutes for DevOps, DataOps and data science work (ad hoc, unique queries benefit less from the cache), and at least 10 minutes for BI and SELECT query warehouses so the cache stays available to users. The other side of the trade-off is that a running warehouse consumes credits even when it is idle. AUTO_SUSPEND is specified in seconds. To check whether a warehouse benefits from its cache, measure the share of data scanned from cache:
SELECT warehouse_name
,COUNT(*) AS query_count
,SUM(bytes_scanned) AS bytes_scanned
,SUM(bytes_scanned*percentage_scanned_from_cache) AS bytes_scanned_from_cache
,SUM(bytes_scanned*percentage_scanned_from_cache) / SUM(bytes_scanned) AS percent_scanned_from_cache
FROM snowflake.account_usage.query_history
WHERE start_time >= dateadd(month,-1,current_timestamp())
AND bytes_scanned > 0
GROUP BY 1
ORDER BY 5;ALTER WAREHOUSE my_wh SET AUTO_SUSPEND = 600;5.When pruning is not happening
Snowflake stores every table as micro-partitions of 50 to 500 MB of uncompressed data. For each micro-partition it keeps metadata, including the range of values in each column. Pruning uses that metadata to skip micro-partitions a filter cannot match. Ideally, a filter that selects 10% of a range scans only about 10% of the micro-partitions. The closer the scanned fraction is to the fraction of data actually selected, the better the pruning.
Two documented causes of poor pruning are worth knowing. One is the predicate itself: Snowflake does not prune on a predicate that contains a subquery, even when the subquery returns a constant. The other is data order. For pruning to help, the storage order of the data needs to be correlated with the query filter attributes. Data that is unsorted or only partly sorted along the filtered dimension spreads matching values over many micro-partitions. This matters most on very large tables. Pruning also only helps queries that actually filter out a significant amount of data.
To spot poor pruning, compare Partitions scanned with Partitions total in the TableScan operators of the Query Profile. If the former is a small fraction of the latter, pruning is efficient. If the pruning statistics show no data reduction, but a Filter operator above the TableScan removes a number of records, that can signal that a different data organization would benefit the query. The same comparison is available in SQL through partitions_scanned and partitions_total:
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;Documented ways to improve pruning: if performance degrades over time, the table may benefit from clustering. A materialized view can define a different clustering key on the same source table, or on a subset of it. The search optimization service can prune the micro-partitions that a query does not need. Select only the columns you need and add selective predicates to the WHERE clause. Put literal values in the filter rather than a subquery.
Checkpoint 6 of 8· Check yourself
A query filters with WHERE sale_date = (SELECT MAX(load_date) FROM batches). The subquery always returns one constant date, but the TableScan reads almost every partition. Why?
Not every predicate can be used for pruning. A predicate with a subquery is never used for pruning, so put the literal value in the filter instead.
“Snowflake does not prune micro-partitions based on a predicate with a subquery, even if the subquery results in a constant.”Source: docs.snowflake.com
Checkpoint 7 of 8· Exam question
A query on a 6 TB EVENTS table filters with WHERE TO_VARCHAR(event_ts, 'YYYY-MM-DD') = '2026-09-30'. The table is clustered on event_ts, yet the Query Profile TableScan shows Partitions scanned equal to Partitions total. What is the MOST likely cause and fix?
Correct answer: B — Wrapping the clustered column in a function prevents micro-partition pruning; rewrite the predicate as a range directly on event_ts
- A. Incorrect. The result cache returns stored results for identical queries and has no role in how many micro-partitions a fresh scan reads.
- B. Correct. Pruning compares the predicate to per-partition min/max values of the raw column, so applying TO_VARCHAR to it blocks pruning; a range predicate on event_ts restores it.
- C. Incorrect. Micro-partition min/max metadata is held in the cloud services layer, not warehouse memory, so resizing does not change pruning.
- D. Incorrect. Even a suspended clustering service leaves existing metadata usable; the scan reads everything because the predicate cannot be matched to the metadata, not because reclustering is pending.
6.Timeout parameters for runaway queries
A hung query keeps using credits until something stops it. There are two timeout parameters to know, and both can be set for the account, a user, a session or a specific warehouse. Both are set at the account level by default. If either is set on both a warehouse and a session, Snowflake enforces the lowest non-zero value.
STATEMENT_TIMEOUT_IN_SECONDS sets the maximum time a SQL statement can run before Snowflake cancels it.
STATEMENT_QUEUED_TIMEOUT_IN_SECONDS sets the maximum time a SQL statement can wait in a warehouse queue before it is canceled. Queued statements do not use credits, but a query that waits too long may no longer be relevant by the time it runs, and running it would waste credits. A value of zero disables the queue timeout.
ALTER ACCOUNT SET STATEMENT_TIMEOUT_IN_SECONDS = <number_of_seconds>;
ALTER USER <username> SET STATEMENT_TIMEOUT_IN_SECONDS = <number_of_seconds>;
ALTER SESSION SET STATEMENT_TIMEOUT_IN_SECONDS = <number_of_seconds>;
ALTER WAREHOUSE <warehouse_name> SET STATEMENT_TIMEOUT_IN_SECONDS = <number_of_seconds>;ALTER ACCOUNT SET STATEMENT_QUEUED_TIMEOUT_IN_SECONDS = <number_of_seconds>;
ALTER USER <username> SET STATEMENT_QUEUED_TIMEOUT_IN_SECONDS = <number_of_seconds>;
ALTER SESSION SET STATEMENT_QUEUED_TIMEOUT_IN_SECONDS = <number_of_seconds>;
ALTER WAREHOUSE <warehouse_name> SET STATEMENT_QUEUED_TIMEOUT_IN_SECONDS = <number_of_seconds>;Checkpoint 8 of 8· Check yourself
A warehouse has STATEMENT_TIMEOUT_IN_SECONDS = 600. An analyst's session sets it to 3600. How long can the analyst's query run on that warehouse?
When both a warehouse and a session set the parameter, the lower non-zero value wins. The session cannot extend the warehouse's limit.
“When the parameter is set for a warehouse in addition to the session, the lowest non-zero value is enforced.”Source: docs.snowflake.com
Sources15
Exam traps
Each one states something that sounds right. Open it to see what is actually true.
1.Any nonzero bytes_spilled_to_remote_storage means the warehouse is too small.Why is that wrong?
With the query acceleration service enabled, Snowflake writes a small amount of data to remote storage for every eligible query, even when QAS is not used for it.
2.If a subquery returns a single constant, Snowflake prunes on it just like a literal.Why is that wrong?
Snowflake never prunes on a predicate that contains a subquery, so the scan reads far more micro-partitions than it needs to.
Covered in When pruning is not happening
3.A Join node that is slow simply needs a bigger warehouse.Why is that wrong?
First check whether the Join outputs far more rows than it takes in. That pattern points to a missing or many-to-many join condition, which is a query-writing problem.
Covered in Troubleshoot common query performance issues: joins, unions and grouping
4.Resuming a suspended warehouse brings back the table data it had cached before.Why is that wrong?
The warehouse cache is dropped when the warehouse suspends, so a resumed warehouse starts with a cold cache and the first queries read from storage again.
5.A query that is logically identical to an earlier one always hits the result cache, even if it adds a table alias or uses lowercase keywords.Why is that wrong?
Result reuse requires an exact match of the query text, so a different alias or different keyword case prevents full reuse.
6.The order of operations in an EXPLAIN plan is the exact order in which Snowflake runs them.Why is that wrong?
EXPLAIN returns a logical plan. It shows the operations and how they relate, but the actual execution order can differ.
Covered in EXPLAIN: the plan before it runs, and how to articulate the execution path
7.STATEMENT_TIMEOUT_IN_SECONDS also limits how long a statement can wait in a warehouse queue.Why is that wrong?
Queue time is controlled by a separate parameter, STATEMENT_QUEUED_TIMEOUT_IN_SECONDS. The statement timeout limits how long a statement runs.
Covered in Timeout parameters for runaway queries
Sources
Every claim above is drawn from one of these pages, quoted as it was written on the date shown.
- 1.
“In the query profile, a parent is shown above its child with a link connecting the two.”
↩︎ Anatomy of a Query Profile: steps, tree, nodes and operator types“Most queries contain a single step, but some are executed as multiple distinct steps.”
↩︎ Anatomy of a Query Profile: steps, tree, nodes and operator types“An explain plan shows the operations (for example, table scans and joins) that Snowflake would perform to execute the query.”
↩︎ EXPLAIN: the plan before it runs, and how to articulate the execution path“The actual execution order of the operations in the plan does not necessarily match the logical order shown by the plan.”
↩︎ EXPLAIN: the plan before it runs, and how to articulate the execution path“The number of partitions from the referenced object that are left after compile-time pruning”
↩︎ EXPLAIN: the plan before it runs, and how to articulate the execution path“Runtime optimizations such as join pruning can reduce the number of partitions and bytes scanned during query execution.”
↩︎ EXPLAIN: the plan before it runs, and how to articulate the execution path“EXPLAIN compiles the SQL statement, but does not execute it, so EXPLAIN does not require a running warehouse.”
↩︎ EXPLAIN: the plan before it runs, and how to articulate the execution path“The actual execution order of the operations in the plan does not necessarily match the logical order shown by the plan.”
↩︎ Exam trap 6“The default is TABULAR.”
↩︎ Checkpoint - 2.
“You can programmatically access the performance statistics of the Query Profile by executing the GET_QUERY_OPERATOR_STATS function.”
↩︎ Anatomy of a Query Profile: steps, tree, nodes and operator types“It includes a Most Expensive Nodes pane that identifies the operator nodes that are taking the longest to execute.”
↩︎ Key concept“In the navigation menu, select Monitoring » Query History.”
↩︎ Checkpoint - 3.
“Represents an operation that filters the records.”
↩︎ Anatomy of a Query Profile: steps, tree, nodes and operator types“UNION ALL simply concatenates inputs, while UNION does the same, but also performs duplicate elimination.”
↩︎ Troubleshoot common query performance issues: joins, unions and grouping“Groups input and computes aggregate functions. Can represent SQL constructs such as GROUP BY, as well as SELECT DISTINCT.”
↩︎ Troubleshoot common query performance issues: joins, unions and grouping“This section describes some of the problems you can identify and troubleshoot using Query Profile.”
↩︎ Troubleshoot common query performance issues: joins, unions and grouping“Non-equality join predicates might result in significantly slower processing speeds and should be avoided if possible.”
↩︎ Troubleshoot common query performance issues: joins, unions and grouping“A query whose result is computed based purely on metadata, without accessing any data.”
↩︎ Data spilling and caching: impact and solutions“If the pruning statistics do not show data reduction, but there is a Filter operator above TableScan which filters out a number of records”
↩︎ When pruning is not happening“For such queries, the Join operator produces significantly (often by orders of magnitude) more tuples than it consumes.”
↩︎ Exam trap 3“These queries show in Query Profile as a UnionAll operator with an extra Aggregate operator on top (which performs duplicate elimination).”
↩︎ Checkpoint - 4.
“These operators typically appear at the bottom of the tree, representing the first step in reading the data”
↩︎ EXPLAIN: the plan before it runs, and how to articulate the execution path“Queries that select from hybrid tables do not benefit from the query results cache.”
↩︎ Data spilling and caching: impact and solutions - 5.
“the cardinality of the GROUP BY expression might be too high for eligibility.”
↩︎ Troubleshoot common query performance issues: joins, unions and grouping - 6.
“The join is missing the join condition. The result is a cross join, which returns every possible combination of rows.”
↩︎ Troubleshoot common query performance issues: joins, unions and grouping“To improve performance, remove the unnecessary DISTINCT or GROUP BY clause.”
↩︎ Troubleshoot common query performance issues: joins, unions and grouping“To avoid this problem, use a larger warehouse that has more capacity, or use a warehouse that has fewer concurrent queries.”
↩︎ Troubleshoot common query performance issues: joins, unions and grouping - 7.
“Latency for the view may be up to 90 minutes.”
↩︎ Troubleshoot common query performance issues: joins, unions and grouping - 8.
“You can use the Query Profile to identify which operation nodes are causing data to spill to storage.”
↩︎ Data spilling and caching: impact and solutions“Using a larger warehouse (effectively increasing the available memory/local storage space for the operation)”
↩︎ Data spilling and caching: impact and solutions“When the query acceleration service (QAS) is enabled, Snowflake writes a small amount of data to remote storage for each eligible query”
↩︎ Exam trap 1“If the query requires even more memory, it spills onto remote cloud-provider storage, which results in even worse performance.”
↩︎ Prediction“Processing data in smaller batches.”
↩︎ Checkpoint - 9.
“Instead of running the query again, Snowflake simply returns the same result that it returned previously.”
↩︎ Data spilling and caching: impact and solutions“For persisted query results of all sizes, the cache expires after 24 hours.”
↩︎ Data spilling and caching: impact and solutions“up to a maximum of 31 days from the date and time that the query was first executed”
↩︎ Data spilling and caching: impact and solutions“By default, result reuse is enabled, but can be overridden at the account, user, and session level using the USE_CACHED_RESULT session parameter.”
↩︎ Data spilling and caching: impact and solutions“Any difference in syntax, including lowercase versus uppercase, or the use of table aliases, will inhibit 100% cache reuse.”
↩︎ Exam trap 5 - 10.
“A running warehouse maintains a cache of table data that can be accessed by queries running on the same warehouse.”
↩︎ Data spilling and caching: impact and solutions“the cache is dropped when the warehouse is suspended”
↩︎ Data spilling and caching: impact and solutions“Snowflake recommends setting auto-suspend to at least 10 minutes to maintain the cache for users.”
↩︎ Data spilling and caching: impact and solutions“Keep in mind that a running warehouse consumes credits even if it is not processing queries.”
↩︎ Data spilling and caching: impact and solutions“the cache is dropped when the warehouse is suspended”
↩︎ Exam trap 4“The warehouse will consume credits while sitting idle without gaining the benefits of a cache because it will be dropped before the next query executes.”
↩︎ Prediction - 11.
“The warehouse was suspended between bursts and resumed for this burst.”
↩︎ Data spilling and caching: impact and solutions - 12.
“Materialized views are more flexible than, but typically slower than, cached results.”
↩︎ Data spilling and caching: impact and solutions - 13.
“If query performance degrades over time, the table is likely no longer well-clustered and may benefit from clustering.”
↩︎ When pruning is not happening“Not all predicate expressions can be used to prune.”
↩︎ Exam trap 2“Snowflake does not prune micro-partitions based on a predicate with a subquery, even if the subquery results in a constant.”
↩︎ Checkpoint - 14.
“First, search optimization can prune the micro-partitions that aren’t needed for a query.”
↩︎ When pruning is not happening - 15.
“you can set the STATEMENT_TIMEOUT_IN_SECONDS parameter to define the maximum amount of time a SQL statement can run before it is canceled.”
↩︎ Timeout parameters for runaway queries“The parameter that controls the amount of time that a SQL statement stays in the queue is STATEMENT_QUEUED_TIMEOUT_IN_SECONDS.”
↩︎ Timeout parameters for runaway queries“The parameter that controls the amount of time that a SQL statement stays in the queue is STATEMENT_QUEUED_TIMEOUT_IN_SECONDS.”
↩︎ Exam trap 7“When the parameter is set for a warehouse in addition to the session, the lowest non-zero value is enforced.”
↩︎ Checkpoint