# Execution plan > Stage by stage, what BigQuery did with a query that has run. Row counts in and out, slot time, shuffle volume, and the performance problems Querylab.io found in the plan. Open it when a query was slower or costlier than the estimate said it would be. Source: https://docs.querylab.io/writing-sql/execution-plan/ **Prism Insights → Execution Plan** **PRISM INSIGHTS** - : Execution Plan
Duration 718ms
Processed 648.1 MB
Cost $0.00
Stages 5
✓ No performance issues detected
Your query executed efficiently!
Execution Stages (5)
Data Flow
fact_mot_test
12.4M rows
↓ Partition filter + GROUP BY (5 partitions){" "} -98.2%
S00: Input
READ AGGREGATE{" "} COMPUTE FILTER{" "} WRITE
224.6K rows
↓ Grouping rows -88.8%
S01: Aggregate+
READ AGGREGATE{" "} COMPUTE WRITE
25.0K rows
A five-stage GROUP BY over fact_mot_test. The first stage reads 12.4M rows and writes 224.6K: partition pruning plus the aggregation removed 98.2% of the data before anything was shuffled. ## Opening it The plan comes from the finished job, so the query has to have run first. Then: - In the editor's status bar, the bytes-and-time text after the cost (`0.15 s elapsed, 648.1 MB`) gets a dotted underline. Click it. - If the Prism Insights panel is already open, its **Execution Plan** view updates by itself when the job finishes. - While a query is still running, the status text is also clickable and shows the stages completed so far. For a multi-statement script the plan belongs to the statement selected in the results bar; pick another statement and the plan follows. In a notebook, each cell's status has its own **View execution plan**. ## Reading the plan ### Summary numbers **Duration**, **Processed** (bytes billed), **Cost** at the tab's pricing, **Stages**, and **Cache** when the result came from BigQuery's cache. When the job reports BI Engine statistics, **BI Engine Accelerated** (with the mode) or **BI Engine Not Used** (with BigQuery's reasons) appears here as well. ### Performance issues Querylab.io flags the problems it finds in the plan. With nothing found, the green card says so. Otherwise each issue has a severity, its impact, the stages involved, and a list of fixes; **Optimize with Prism AI** hands the plan and the query to the [agent](https://docs.querylab.io/prism-ai/introduction/) with the issues already in context. | Issue | What the plan showed | | --------------------------------- | ------------------------------------------------------------------------------------------ | | Partition Pruning Failed | A partitioned table was scanned in full; the filter on the partition column didn't prune | | Late Filtering Detected | Filters were applied in a later stage, after bytes had already been processed and shuffled | | Join Explosion Detected | A join stage wrote many times more rows than it read | | Data Skew Detected | One worker did a disproportionate share of a stage's work | | Sequential Aggregation Bottleneck | An aggregation couldn't be parallelized and took a large share of the total time | | Shuffle Spill to Disk | Shuffle data exceeded memory and spilled to disk | | Slot Starvation Detected | The query waited for slots | | Insufficient Shuffle Quota | The shuffle quota, not compute, was the limit | | Query Performance Regression | This run took several times longer than the average of its previous runs | | BI Engine Not Used | BI Engine acceleration was available but not used | ### Execution stages Collapsed by default. It opens with the **Data Flow** chart: the source tables with their row counts, then each stage's operations and the rows it wrote, with the percentage change between stages and its reason: _Partition filter_, _GROUP BY_, _Filtering_, _Joining tables_. A stage that multiplies rows is marked with the factor. Below the chart, one card per stage with its status, operations, duration, records read and written, shuffle bytes, and BigQuery's own step list. **Slot-ms** is the slot time the stage consumed, which is what a reservation pays for. The slowest stage carries a **BOTTLENECK** tag. ⌘-click (Ctrl-click on Windows and Linux) a stage card to select the SQL it came from in the editor. When a query has parallel branches (a join reading two tables, a `UNION ALL`), the stages are drawn as a graph above the cards, left to right by dependency, with the critical path in orange and the bottleneck stage flagged. Straight-line queries skip the graph. > The plan explains a run; the [cost breakdown](https://docs.querylab.io/writing-sql/insights-panel/) predicts one. When a plan shows Partition Pruning Failed, fix the filter, then use Analyze on the cost view to confirm the bytes dropped before you run it again.