Skip to content

Commit 66be6df

Browse files
Merge pull request #292 from erikdarlingdata/dev
Release: dev -> main
2 parents 194d1fc + 909290e commit 66be6df

28 files changed

Lines changed: 1388 additions & 402 deletions

README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,11 @@ Side-by-side comparison of two plans showing cost, runtime, I/O, memory, and wai
5757
### Query Store Integration
5858
Fetch top queries by CPU, duration, logical reads, physical reads, writes, memory, or executions from Query Store and load their plans directly into the analyzer.
5959

60-
![Query Store Integration](screenshots/Query%20Store%20Integration.png)
60+
![Query Store Integration](screenshots/performance_studio_querystore_analysis_top_cpu_by_query_hash.png)
61+
62+
### Minimap and colored links by accuracy ratio divergence
63+
The minimap provides a high-level overview of the entire plan, allowing you to quickly navigate to areas of interest. Colored links between operators indicate accuracy ratio divergence, helping you identify where estimates are most off from actuals.
64+
![Minimap and Colored Links](screenshots/minimap_and_planviewer_colored_actual_plan.png)
6165

6266
### MCP Integration
6367
Ask Claude Code to analyze loaded plans, identify warnings, suggest indexes, and compare plans — all through the built-in MCP server.
@@ -299,6 +303,8 @@ Features:
299303
- Warning badge on root node showing total warning count
300304
- Plan Insights panel — three-column view with runtime summary, missing indexes, and wait stats visualization
301305
- Zoom and pan (mouse wheel + middle-click drag)
306+
- Minimap for quick navigation of large plans
307+
- Color-coded links between operators based on accuracy ratio divergence (estimates vs actuals)
302308
- Click any operator to see full properties (30 sections)
303309
- Statement grid with sortable columns (cost, rows, DOP, warnings)
304310
- Tooltips on hover with key operator metrics
@@ -308,6 +314,7 @@ Features:
308314
- **Copy Repro Script** — extracts parameters, SET options, and query text into a runnable `sp_executesql` script
309315
- **Get Actual Plan** — connect to a server and re-execute the query to capture runtime stats
310316
- **Query Store Analysis** — connect to a server and analyze top queries by CPU, duration, or reads
317+
- **Query History** — view a history of executed queries with their plans along the timeline and metrics from query store
311318
- **MCP Server** — built-in Model Context Protocol server for AI-assisted plan analysis (opt-in)
312319
- Dark theme
313320

504 KB
Loading
1.07 MB
Loading

src/PlanViewer.App/Controls/PlanViewerControl.axaml

Lines changed: 72 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@
190190
</Border>
191191

192192
<!-- Statements Panel + Plan Canvas + Properties Panel -->
193-
<Grid Grid.Row="2">
193+
<Grid x:Name="PlanGrid" Grid.Row="2">
194194
<Grid.ColumnDefinitions>
195195
<!-- Col 0: Statements Panel (hidden by default) -->
196196
<ColumnDefinition Width="0"/>
@@ -255,21 +255,77 @@
255255
Background="{DynamicResource BorderBrush}"
256256
IsVisible="False"/>
257257

258-
<!-- Plan Canvas -->
259-
<ScrollViewer Grid.Column="2" x:Name="PlanScrollViewer"
260-
HorizontalScrollBarVisibility="Auto"
261-
VerticalScrollBarVisibility="Auto"
262-
HorizontalContentAlignment="Left"
263-
VerticalContentAlignment="Top"
264-
Background="{DynamicResource BackgroundBrush}">
265-
<LayoutTransformControl x:Name="PlanLayoutTransform"
266-
HorizontalAlignment="Left" VerticalAlignment="Top">
267-
<LayoutTransformControl.LayoutTransform>
268-
<ScaleTransform ScaleX="1" ScaleY="1"/>
269-
</LayoutTransformControl.LayoutTransform>
270-
<Canvas x:Name="PlanCanvas" ClipToBounds="False"/>
271-
</LayoutTransformControl>
272-
</ScrollViewer>
258+
<!-- Plan Canvas + Minimap overlay -->
259+
<Grid Grid.Column="2">
260+
<ScrollViewer x:Name="PlanScrollViewer"
261+
HorizontalScrollBarVisibility="Auto"
262+
VerticalScrollBarVisibility="Auto"
263+
HorizontalContentAlignment="Left"
264+
VerticalContentAlignment="Top"
265+
Background="{DynamicResource BackgroundBrush}">
266+
<LayoutTransformControl x:Name="PlanLayoutTransform"
267+
HorizontalAlignment="Left" VerticalAlignment="Top">
268+
<LayoutTransformControl.LayoutTransform>
269+
<ScaleTransform ScaleX="1" ScaleY="1"/>
270+
</LayoutTransformControl.LayoutTransform>
271+
<Canvas x:Name="PlanCanvas" ClipToBounds="False"/>
272+
</LayoutTransformControl>
273+
</ScrollViewer>
274+
275+
<!-- Minimap toggle button (top-left, always visible) -->
276+
<Button x:Name="MinimapToggleButton" Content="minimap"
277+
Click="MinimapToggle_Click"
278+
HorizontalAlignment="Left" VerticalAlignment="Top"
279+
Margin="4,4,0,0" Padding="4,1" FontSize="9"
280+
Height="18" MinWidth="0" MinHeight="0"
281+
Opacity="0.8" ZIndex="10"
282+
Theme="{StaticResource AppButton}"
283+
ToolTip.Tip="Show/hide minimap"/>
284+
285+
<!-- Minimap panel -->
286+
<Border x:Name="MinimapPanel" IsVisible="False"
287+
HorizontalAlignment="Left" VerticalAlignment="Top"
288+
Margin="4,26,0,0" ZIndex="10"
289+
Width="400" Height="400"
290+
Background="{DynamicResource BackgroundBrush}"
291+
BorderBrush="{DynamicResource BorderBrush}" BorderThickness="5"
292+
CornerRadius="4" ClipToBounds="True">
293+
<Grid>
294+
<Grid.RowDefinitions>
295+
<RowDefinition Height="Auto"/>
296+
<RowDefinition Height="*"/>
297+
</Grid.RowDefinitions>
298+
<!-- Minimap header with close button -->
299+
<DockPanel Grid.Row="0" Background="{DynamicResource BackgroundBrush}">
300+
<Button DockPanel.Dock="Right" Content="&#x2715;" Click="MinimapClose_Click"
301+
Width="18" Height="18" Padding="0" FontSize="10"
302+
VerticalAlignment="Center" Margin="0,0,2,0"
303+
Theme="{StaticResource AppButton}" ToolTip.Tip="Close minimap"/>
304+
<TextBlock Text="Minimap" FontSize="10" VerticalAlignment="Center"
305+
Margin="4,1,0,1"
306+
Foreground="{DynamicResource ForegroundBrush}"/>
307+
</DockPanel>
308+
<!-- Minimap canvas -->
309+
<Canvas x:Name="MinimapCanvas" Grid.Row="1" ClipToBounds="True"
310+
Background="{DynamicResource BackgroundBrush}"/>
311+
<!-- Resize grip (bottom-right corner) -->
312+
<Border x:Name="MinimapResizeGrip" Grid.Row="1"
313+
Width="14" Height="14"
314+
HorizontalAlignment="Right" VerticalAlignment="Bottom"
315+
Background="Transparent"
316+
Cursor="BottomRightCorner">
317+
<Canvas Width="10" Height="10" Margin="1,1,3,3">
318+
<Line StartPoint="6,10" EndPoint="10,6"
319+
Stroke="{DynamicResource ForegroundBrush}" StrokeThickness="1" Opacity="0.5"/>
320+
<Line StartPoint="3,10" EndPoint="10,3"
321+
Stroke="{DynamicResource ForegroundBrush}" StrokeThickness="1" Opacity="0.5"/>
322+
<Line StartPoint="0,10" EndPoint="10,0"
323+
Stroke="{DynamicResource ForegroundBrush}" StrokeThickness="1" Opacity="0.5"/>
324+
</Canvas>
325+
</Border>
326+
</Grid>
327+
</Border>
328+
</Grid>
273329

274330
<!-- Empty State -->
275331
<StackPanel x:Name="EmptyState" Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Center">

0 commit comments

Comments
 (0)