You've already forked explain.depesz.com
mirror of
https://gitlab.com/depesz/explain.depesz.com.git
synced 2025-12-03 23:19:13 +02:00
275 lines
10 KiB
Plaintext
275 lines
10 KiB
Plaintext
|
|
% layout 'default';
|
||
|
|
|
||
|
|
% my $title = stash( 'plan_id' );
|
||
|
|
% title $title;
|
||
|
|
|
||
|
|
% my $row = 0;
|
||
|
|
%
|
||
|
|
% my $row_class = begin
|
||
|
|
% my $class = shift;
|
||
|
|
%
|
||
|
|
% my $next = scalar( @_ ) ? shift : 1;
|
||
|
|
%
|
||
|
|
% ++$row if $next;
|
||
|
|
%
|
||
|
|
% return sprintf '%s %s', $class, $row % 2 ? 'odd' : 'even';
|
||
|
|
% end;
|
||
|
|
|
||
|
|
% my $block = undef;
|
||
|
|
%
|
||
|
|
% $block = begin
|
||
|
|
%
|
||
|
|
% my ( $node, $level ) = @_;
|
||
|
|
%
|
||
|
|
% $level ||= 0;
|
||
|
|
%
|
||
|
|
% my $exclusive_point = 1;
|
||
|
|
% my $inclusive_point = 1;
|
||
|
|
%
|
||
|
|
% if ( $explain->top_node->total_inclusive_time && $node->total_exclusive_time ne '' && $node->total_inclusive_time ne '' ) {
|
||
|
|
%
|
||
|
|
% $exclusive_point = $node->total_exclusive_time / $explain->top_node->total_inclusive_time;
|
||
|
|
%
|
||
|
|
% if ( $exclusive_point > 0.9 ) { $exclusive_point = 4; }
|
||
|
|
% elsif ( $exclusive_point > 0.5 ) { $exclusive_point = 3; }
|
||
|
|
% elsif ( $exclusive_point > 0.1 ) { $exclusive_point = 2; }
|
||
|
|
% else { $exclusive_point = 1; }
|
||
|
|
%
|
||
|
|
% $inclusive_point = $node->total_inclusive_time / $explain->top_node->total_inclusive_time;
|
||
|
|
%
|
||
|
|
% if ( $inclusive_point > 0.9 ) { $inclusive_point = 4; }
|
||
|
|
% elsif ( $inclusive_point > 0.5 ) { $inclusive_point = 3; }
|
||
|
|
% elsif ( $inclusive_point > 0.1 ) { $inclusive_point = 2; }
|
||
|
|
% else { $inclusive_point = 1; }
|
||
|
|
% }
|
||
|
|
%
|
||
|
|
% my $rows_x = 0;
|
||
|
|
% my $rows_x_mark = '';
|
||
|
|
% my $rows_x_point = 1;
|
||
|
|
%
|
||
|
|
% if ( $node->estimated_rows && $node->actual_rows ) {
|
||
|
|
%
|
||
|
|
% if ( $node->actual_rows > $node->estimated_rows ) {
|
||
|
|
% $rows_x = $node->actual_rows / $node->estimated_rows;
|
||
|
|
% $rows_x_mark = 'down';
|
||
|
|
% } else {
|
||
|
|
% $rows_x = $node->estimated_rows / $node->actual_rows;
|
||
|
|
% $rows_x_mark = 'up';
|
||
|
|
% }
|
||
|
|
%
|
||
|
|
% if ( $rows_x > 1000 ) { $rows_x_point = 4; }
|
||
|
|
% elsif ( $rows_x > 100 ) { $rows_x_point = 3; }
|
||
|
|
% elsif ( $rows_x > 10 ) { $rows_x_point = 2; }
|
||
|
|
% else { $rows_x_point = 1; }
|
||
|
|
% }
|
||
|
|
|
||
|
|
%# tr class="(n|ip|sp) (even|odd) c-(mix|1|2|3|4)"
|
||
|
|
%# means:
|
||
|
|
%# n(ode)/i(nit)p(lan)/s(ub)p(lan)
|
||
|
|
%# c(olor)-mix(ed)|1|2|3|4
|
||
|
|
%#
|
||
|
|
%# td class="(e|i|x|r|l|n) (c-(1|2|3|4))?"
|
||
|
|
%# means:
|
||
|
|
%# e(xclusive time)/i(nclusive time)/(rows-)x/r(ows)/l(oops)/n(ode)
|
||
|
|
%# c(olor)-1|2|3|4
|
||
|
|
%#
|
||
|
|
%# important!
|
||
|
|
%# content of td.r(ows)/td.l(oops) must be wrapped in "span" element (because Opera...)
|
||
|
|
|
||
|
|
% my $margin = ( $level + 1 ) * 22;
|
||
|
|
|
||
|
|
<tr class="<%= $row_class->( 'n c-mix' ) =%>" data-level="<%= $level =%>" data-e="<%= $exclusive_point =%>" data-i="<%= $inclusive_point =%>" data-x="<%= $rows_x_point =%>">
|
||
|
|
<td class="e c-<%= $exclusive_point =%>"><%= sprintf '%.3f', $node->total_exclusive_time =%></td>
|
||
|
|
<td class="i c-<%= $inclusive_point =%>"><%= sprintf '%.3f', $node->total_inclusive_time =%></td>
|
||
|
|
<td class="x c-<%= $rows_x_point =%>">
|
||
|
|
<span class="rows-x-ico rows-x-ico-<%= $rows_x_mark %>">
|
||
|
|
<%= b( $rows_x_mark eq 'up' ? '↑' : '↓' ) =%>
|
||
|
|
</span>
|
||
|
|
<%= sprintf '%.1f', $rows_x %>
|
||
|
|
</td>
|
||
|
|
<td class="r"><span><%= $node->actual_rows =%></span></td>
|
||
|
|
<td class="l"><span><%= $node->actual_loops =%></span></td>
|
||
|
|
<td class="n">
|
||
|
|
<div class="n" style="margin-left:<%= $margin =%>px">
|
||
|
|
|
||
|
|
<div class="ico">→</div>
|
||
|
|
|
||
|
|
<p>
|
||
|
|
<span class="node">
|
||
|
|
|
||
|
|
<%= $node->type %>
|
||
|
|
|
||
|
|
% if ( 'Bitmap Heap Scan' eq $node->type ) {
|
||
|
|
on <%= $node->scan_on->{ table_name } %> <%= $node->scan_on->{ table_alias } || '' %>
|
||
|
|
% }
|
||
|
|
% elsif ( 'Bitmap Index Scan' eq $node->type ) {
|
||
|
|
on <%= $node->scan_on->{ index_name } %>
|
||
|
|
% }
|
||
|
|
% elsif ( 'Index Scan' eq $node->type ) {
|
||
|
|
using <%= $node->scan_on->{ index_name } %> on <%= $node->scan_on->{ table_name } %> <%= $node->scan_on->{ table_alias } || '' %>
|
||
|
|
% }
|
||
|
|
% elsif ( 'Seq Scan' eq $node->type ) {
|
||
|
|
on <%= $node->scan_on->{ table_name } %> <%= $node->scan_on->{ table_alias } || '' %>
|
||
|
|
% }
|
||
|
|
|
||
|
|
</span>
|
||
|
|
|
||
|
|
<span class="est">
|
||
|
|
(cost=<%= $node->estimated_startup_cost =%>..<%= $node->estimated_total_cost %>
|
||
|
|
rows=<%= $node->estimated_rows %>
|
||
|
|
width=<%= $node->estimated_row_width =%>)
|
||
|
|
</span>
|
||
|
|
|
||
|
|
<span class="act">
|
||
|
|
(actual
|
||
|
|
time=<%= $node->actual_time_first =%>..<%= $node->actual_time_last %>
|
||
|
|
rows=<%= $node->actual_rows %>
|
||
|
|
loops=<%= $node->actual_loops =%>)
|
||
|
|
</span>
|
||
|
|
</p>
|
||
|
|
|
||
|
|
% if ( $node->extra_info ) {
|
||
|
|
<ul class="ex-nfo">
|
||
|
|
% for my $line ( @{ $node->extra_info } ) {
|
||
|
|
<li><%= $line =%></li>
|
||
|
|
% }
|
||
|
|
</ul>
|
||
|
|
% }
|
||
|
|
|
||
|
|
</div>
|
||
|
|
</td>
|
||
|
|
</tr>
|
||
|
|
|
||
|
|
% if ( $node->initplans ) {
|
||
|
|
|
||
|
|
<tr class="<%= $row_class->( 'ip' ) %>" data-level="<%= $level =%>">
|
||
|
|
<td class="e"> </td>
|
||
|
|
<td class="i"> </td>
|
||
|
|
<td class="x"> </td>
|
||
|
|
<td class="r"><span> </span></td>
|
||
|
|
<td class="l"><span> </span></td>
|
||
|
|
<td class="n">
|
||
|
|
<div class="n" style="margin-left:<%= $margin =%>px">
|
||
|
|
<p><span>Initplan (for <%= $node->type =%>)</span></p>
|
||
|
|
</div>
|
||
|
|
</td>
|
||
|
|
</tr>
|
||
|
|
|
||
|
|
% for ( @{ $node->initplans } ) {
|
||
|
|
%== $block->( $_, $level + 1 );
|
||
|
|
% }
|
||
|
|
% }
|
||
|
|
|
||
|
|
% if ( $node->sub_nodes ) {
|
||
|
|
% for ( @{ $node->sub_nodes } ) {
|
||
|
|
%== $block->( $_, $level + 1 );
|
||
|
|
% }
|
||
|
|
% }
|
||
|
|
|
||
|
|
% if ( $node->subplans ) {
|
||
|
|
|
||
|
|
<tr class="<%= $row_class->( 'sp' ) %>" data-level="<%= $level =%>">
|
||
|
|
<td class="e"> </td>
|
||
|
|
<td class="i"> </td>
|
||
|
|
<td class="x"> </td>
|
||
|
|
<td class="r"><span> </span></td>
|
||
|
|
<td class="l"><span> </span></td>
|
||
|
|
<td class="n">
|
||
|
|
<div class="n" style="margin-left:<%= $margin =%>px">
|
||
|
|
<p><span>SubPlan (for <%= $node->type =%>)</span></p>
|
||
|
|
</div>
|
||
|
|
</td>
|
||
|
|
</tr>
|
||
|
|
|
||
|
|
% for ( @{ $node->subplans } ) {
|
||
|
|
%== $block->( $_, $level + 1 );
|
||
|
|
% }
|
||
|
|
% }
|
||
|
|
|
||
|
|
% end;
|
||
|
|
|
||
|
|
<h1>Results</h1>
|
||
|
|
|
||
|
|
<div class="result">
|
||
|
|
|
||
|
|
<div class="tabs">
|
||
|
|
<ul class="clearfix">
|
||
|
|
<li class="html">
|
||
|
|
<a href="#html"
|
||
|
|
title="view HTML"
|
||
|
|
class="current"
|
||
|
|
onclick="$( this ).explain( 'toggleView', 'html' ); return false;"
|
||
|
|
onkeypress="return this.onclick( );">HTML</a>
|
||
|
|
</li>
|
||
|
|
<li class="text">
|
||
|
|
<a href="#text"
|
||
|
|
title="view plain text"
|
||
|
|
onclick="$( this ).explain( 'toggleView', 'text' ); return false;"
|
||
|
|
onkeypress="return this.onclick( );">TEXT</a>
|
||
|
|
</li>
|
||
|
|
</ul>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- HTML view -->
|
||
|
|
<div class="result-html">
|
||
|
|
<table id="explain">
|
||
|
|
<thead>
|
||
|
|
<tr>
|
||
|
|
<th class="e">
|
||
|
|
<a href="#colorize-exclusive"
|
||
|
|
title="colorize rows based on "exclusive""
|
||
|
|
onclick="$( this ).explain( 'colorize', 'e', this ); return false"
|
||
|
|
onkeypress="return this.onclick( );">exclusive</a>
|
||
|
|
</th>
|
||
|
|
<th class="i">
|
||
|
|
<a href="#colorize-inclusive"
|
||
|
|
title="colorize rows based on "inclusive""
|
||
|
|
onclick="$( this ).explain( 'colorize', 'i', this ); return false"
|
||
|
|
onkeypress="return this.onclick( );">inclusive</a>
|
||
|
|
</th>
|
||
|
|
<th class="x">
|
||
|
|
<a href="#colorize-rows-x"
|
||
|
|
title="colorize rows based on "rows x""
|
||
|
|
onclick="$( this ).explain( 'colorize', 'x', this ); return false"
|
||
|
|
onkeypress="return this.onclick( );">rows x</a>
|
||
|
|
</th>
|
||
|
|
<th class="r">
|
||
|
|
<a href="#toggle-rows"
|
||
|
|
title="expland/collapse "rows" column"
|
||
|
|
onclick="$( this ).explain( 'toggleColumn', 'r', this ); return false"
|
||
|
|
onkeypress="return this.onclick( );">rows</a>
|
||
|
|
</th>
|
||
|
|
<th class="l">
|
||
|
|
<a href="#toggle-loops"
|
||
|
|
title="expland/collapse "loops" column"
|
||
|
|
onclick="$( this ).explain( 'toggleColumn', 'l', this ); return false"
|
||
|
|
onkeypress="return this.onclick( );">loops</a>
|
||
|
|
</th>
|
||
|
|
<th class="n">
|
||
|
|
<a href="#column-mixed"
|
||
|
|
title="colorize rows "mixed" style"
|
||
|
|
onclick="$( this ).explain( 'colorize', null, this ); return false"
|
||
|
|
onkeypress="return this.onclick( );">node</a>
|
||
|
|
</th>
|
||
|
|
</tr>
|
||
|
|
</thead>
|
||
|
|
<tbody>
|
||
|
|
%== $block->( $explain->top_node );
|
||
|
|
</tbody>
|
||
|
|
</table>
|
||
|
|
<% content_for 'head' => begin %>
|
||
|
|
<script>
|
||
|
|
$( document ).ready( function( ) {
|
||
|
|
$( '#explain' ).explain( );
|
||
|
|
} );
|
||
|
|
</script>
|
||
|
|
<% end %>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- TEXT view -->
|
||
|
|
<div class="result-text hidden">
|
||
|
|
<pre id="source"><%= $explain->source =%></pre>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
</div>
|