Oracle database experiences

Oracle database blog

Generating SVG graphics with SQL*Plus – Part XVI – Vertical stacked bar graph

Scope

In some situations it could be interesting to use a vertical stacked bar graph in order to display data. We will display the wait classes given by the view v$waitclassmetric_history. We will use the query defined in the part VI as a starting point. We will modify the source query as follow:

SELECT TO_CHAR(begin_time,'HH24:MI') BEGIN_TIME
,      c_other          C_OTHER
,      c_application    C_APPLICATION
,      c_configuration  C_CONFIGURATION
,      c_administrative C_ADMINISTRATIVE
,      c_concurrency    C_CONCURRENCY
,      c_commit         C_COMMIT
,      c_network        C_NETWORK
,      c_user_io        C_USER_IO
,      c_system_io      C_SYSTEM_IO
,      c_scheduler      C_SCHEDULER
,      c_cluster        C_CLUSTER
,      c_queueing       C_QUEUEING
,      MAX(c_queueing) OVER() SUM_TIME_WAITED
        FROM (
           SELECT * 
           FROM (
              SELECT begin_time
              ,      wait_class#
              ,      SUM(time_waited) OVER (PARTITION BY begin_time ORDER BY wait_class#) sum_time_waited_acc
              FROM v$waitclassmetric_history
              WHERE wait_class# <> 6
                ) tb 
           PIVOT (
              MAX(sum_time_waited_acc) 
              FOR wait_class# IN (0 AS c_other, 1 AS c_application,2 AS c_configuration,3 AS c_administrative,4 AS c_concurrency,5 AS c_commit, 
                                  7 AS c_network, 8 AS c_user_io, 9 AS c_system_io, 10 AS c_scheduler,11 AS c_cluster,12 AS c_queueing)
                 )
           ORDER BY begin_time
             )
        ORDER BY begin_time

Basically the query will:

  • Select all the wait classes from the view v$waitclassmetric_history except for the wait class 6 (Idle),
  • Cumulate the value of the column time_waited through all the wait classes in the same class order,
  • Pivot the cumulated time_waited column of each wait class and give a name to the new columns e.g. c_user.

XSLT variables

We will add one additional variable in the XSLT document:

  • <xsl:variable name="margin_right">100</xsl:variable>

    Right margin of the SVG graph.

Furthermore:

  • The variable “graph_name” is set to ‘Wait Classes’,
  • The variable “graph_unit” is set to ‘Time waited (in microseconds)’,
  • The variable “yval_min” is set to 0,
  • The variable “yval_max” is set to the first value of the column SUM_TIME_WAITED.

Stacked bar

The stacked bar is build as follow:

  • The values of the different wait classes are stacked in the same order (C_OTHER to C_QUEUEING) using “sub-bar”,
  • The starting point of each “sub-bar” is the value given by the column C_OTHER..C_QUEUEING e.g.
    y="{round(($graph_height)-($margin_bottom)-((($yval_min)-(descendant::C_APPLICATION))*(100 div (($yval_min)-($yval_max)))))}"
  • The height of the “sub-bar” is the difference between the current wait class value minus the previous wait class value (except for the first one) e.g.
    height="{round((((descendant::C_OTHER)-(C_APPLICATION))*(100 div (($yval_min)-($yval_max)))))}"
  • Each “sub-bar” has a different filled color.

Modified query

You will find below the modified query:

SET LINESIZE      300
SET LONGCHUNKSIZE 100000
SET LONG          100000

SET FEEDBACK OFF
SET VERIFY   OFF
SET PAGESIZE 0

SET HEADING OFF

SPOOL generate_svg_16i.svg

SELECT XMLTRANSFORM
   (DBMS_XMLGEN.GETXMLTYPE
      ('SELECT TO_CHAR(begin_time,''HH24:MI'') BEGIN_TIME
        ,      c_other          C_OTHER
        ,      c_application    C_APPLICATION
        ,      c_configuration  C_CONFIGURATION
        ,      c_administrative C_ADMINISTRATIVE
        ,      c_concurrency    C_CONCURRENCY
        ,      c_commit         C_COMMIT
        ,      c_network        C_NETWORK
        ,      c_user_io        C_USER_IO
        ,      c_system_io      C_SYSTEM_IO
        ,      c_scheduler      C_SCHEDULER
        ,      c_cluster        C_CLUSTER
        ,      c_queueing       C_QUEUEING
        ,      MAX(c_queueing) OVER() SUM_TIME_WAITED
        FROM (
           SELECT * 
           FROM (
              SELECT begin_time
              ,      wait_class#
              ,      SUM(time_waited) OVER (PARTITION BY begin_time ORDER BY wait_class#) sum_time_waited_acc
              FROM v$waitclassmetric_history
              WHERE wait_class# <> 6
                ) tb 
           PIVOT (
              MAX(sum_time_waited_acc) 
              FOR wait_class# IN (0 AS c_other, 1 AS c_application,2 AS c_configuration,3 AS c_administrative,4 AS c_concurrency,5 AS c_commit, 
                                  7 AS c_network, 8 AS c_user_io, 9 AS c_system_io, 10 AS c_scheduler,11 AS c_cluster,12 AS c_queueing)
                 )
           ORDER BY begin_time
             )
        ORDER BY begin_time')
,      XMLTYPE.CREATEXML
   (TO_CLOB(
    '<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
     <xsl:variable name="margin_top">20</xsl:variable>
     <xsl:variable name="margin_bottom">30</xsl:variable>
     <xsl:variable name="margin_left">40</xsl:variable>
     <xsl:variable name="margin_right">100</xsl:variable>
     <xsl:variable name="bar_width">5</xsl:variable>
     <xsl:variable name="graph_width"><xsl:value-of select="315+$margin_left+$margin_right"/></xsl:variable>
     <xsl:variable name="graph_height"><xsl:value-of select="100+$margin_top+$margin_bottom"/></xsl:variable>
     <xsl:variable name="graph_name">Wait Classes</xsl:variable>
     <xsl:variable name="graph_unit">Time waited (in microseconds)</xsl:variable>
     <xsl:variable name="yval_max"><xsl:value-of select="/descendant::SUM_TIME_WAITED[position()=1]"/></xsl:variable>
     <xsl:variable name="yval_min">0</xsl:variable>
       <xsl:template match="/">
         <svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" width="{$graph_width}" height="{$graph_height}">
           <text x="{$margin_left+1}" y="{($margin_top)-5}" style="fill: #000000; stroke: none;font-size:10px;text-anchor=start"><xsl:value-of select="$graph_name"/></text>
           <text x="{($margin_bottom)-($graph_height)}" y="10" transform="rotate(-90)" style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="$graph_unit"/></text>
           <line x1="{($margin_left)-5}" y1="{($graph_height)-($margin_bottom)-0}"   x2="{($graph_width)-($margin_right)+5}" y2="{($graph_height)-($margin_bottom)-0}"  style="stroke:lightblue;stroke-width:1" />
           <line x1="{($margin_left)-5}" y1="{($graph_height)-($margin_bottom)-25}"  x2="{($graph_width)-($margin_right)+5}" y2="{($graph_height)-($margin_bottom)-25}" style="stroke:lightblue;stroke-width:1" />
           <line x1="{($margin_left)-5}" y1="{($graph_height)-($margin_bottom)-50}"  x2="{($graph_width)-($margin_right)+5}" y2="{($graph_height)-($margin_bottom)-50}" style="stroke:lightblue;stroke-width:1" />
           <line x1="{($margin_left)-5}" y1="{($graph_height)-($margin_bottom)-75}"  x2="{($graph_width)-($margin_right)+5}" y2="{($graph_height)-($margin_bottom)-75}" style="stroke:lightblue;stroke-width:1" />
           <line x1="{($margin_left)-5}" y1="{($graph_height)-($margin_bottom)-100}" x2="{($graph_width)-($margin_right)+5}" y2="{($graph_height)-($margin_bottom)-100}" style="stroke:lightblue;stroke-width:1" />
           <text x="{($margin_left)-20}" y="{($graph_height)-($margin_bottom)-2}"   style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="round($yval_min)"/></text>
           <text x="{($margin_left)-20}" y="{($graph_height)-($margin_bottom)-25}"  style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="round(($yval_min)+(1*(($yval_max)-($yval_min)) div 4))"/></text>
           <text x="{($margin_left)-20}" y="{($graph_height)-($margin_bottom)-50}"  style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="round(($yval_min)+((($yval_max)-($yval_min)) div 2))"/></text>
           <text x="{($margin_left)-20}" y="{($graph_height)-($margin_bottom)-75}"  style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="round(($yval_min)+(3*(($yval_max)-($yval_min)) div 4))"/></text>
           <text x="{($margin_left)-20}" y="{($graph_height)-($margin_bottom)-100}" style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="round($yval_max)"/></text>
           <line x1="{$margin_left}" y1="{($graph_height)-($margin_bottom)}" x2="{$margin_left}" y2="{($graph_height)-($margin_bottom)-100}" style="stroke:lightblue;stroke-width:1" />'
           ) 
    || 
    TO_CLOB(
          '<xsl:for-each select="ROWSET/ROW/BEGIN_TIME">
             <xsl:choose>
               <xsl:when test="(position()-1) mod 5=0">
                 <text x="{($margin_left)-9+($bar_width*(position()-1))}" y="{($graph_height)-($margin_bottom)+12}" style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="self::node()"/></text>
                 <line x1="{($margin_left)+($bar_width*(position()-1))}" y1="{($graph_height)-($margin_bottom)+4}" x2="{($margin_left)+($bar_width*(position()-1))}" y2="{($graph_height)-($margin_bottom)-100}" style="stroke:lightblue;stroke-width:1" /> 
               </xsl:when>
             </xsl:choose>    
           </xsl:for-each>
           <xsl:for-each select="ROWSET/ROW">
             <rect x="{$margin_left+$bar_width*(position()-1)}" y="{round(($graph_height)-($margin_bottom)-((($yval_min)-(descendant::C_OTHER))*(100 div (($yval_min)-($yval_max)))))}" width="{$bar_width}" height="{round(((($yval_min)-(descendant::C_OTHER))*(100 div (($yval_min)-($yval_max)))))}" fill="hotpink" stroke="black"/> 
             <rect x="{$margin_left+$bar_width*(position()-1)}" y="{round(($graph_height)-($margin_bottom)-((($yval_min)-(descendant::C_APPLICATION))*(100 div (($yval_min)-($yval_max)))))}" width="{$bar_width}" height="{round((((descendant::C_OTHER)-(C_APPLICATION))*(100 div (($yval_min)-($yval_max)))))}" fill="indianred" stroke="black"/>                                                                                                                                    
             <rect x="{$margin_left+$bar_width*(position()-1)}" y="{round(($graph_height)-($margin_bottom)-((($yval_min)-(descendant::C_CONFIGURATION))*(100 div (($yval_min)-($yval_max)))))}" width="{$bar_width}" height="{round((((descendant::C_APPLICATION)-(C_CONFIGURATION))*(100 div (($yval_min)-($yval_max)))))}" fill="olive" stroke="black"/>   
             <rect x="{$margin_left+$bar_width*(position()-1)}" y="{round(($graph_height)-($margin_bottom)-((($yval_min)-(descendant::C_ADMINISTRATIVE))*(100 div (($yval_min)-($yval_max)))))}" width="{$bar_width}" height="{round((((descendant::C_CONFIGURATION)-(C_ADMINISTRATIVE))*(100 div (($yval_min)-($yval_max)))))}" fill="gray" stroke="black"/>   
             <rect x="{$margin_left+$bar_width*(position()-1)}" y="{round(($graph_height)-($margin_bottom)-((($yval_min)-(descendant::C_CONCURRENCY))*(100 div (($yval_min)-($yval_max)))))}" width="{$bar_width}" height="{round((((descendant::C_ADMINISTRATIVE)-(C_CONCURRENCY))*(100 div (($yval_min)-($yval_max)))))}" fill="sienna" stroke="black"/>   
             <rect x="{$margin_left+$bar_width*(position()-1)}" y="{round(($graph_height)-($margin_bottom)-((($yval_min)-(descendant::C_COMMIT))*(100 div (($yval_min)-($yval_max)))))}" width="{$bar_width}" height="{round((((descendant::C_CONCURRENCY)-(C_COMMIT))*(100 div (($yval_min)-($yval_max)))))}" fill="orange" stroke="black"/>'
           ) 
    || 
    TO_CLOB(
          '  <rect x="{$margin_left+$bar_width*(position()-1)}" y="{round(($graph_height)-($margin_bottom)-((($yval_min)-(descendant::C_NETWORK))*(100 div (($yval_min)-($yval_max)))))}" width="{$bar_width}" height="{round((((descendant::C_COMMIT)-(C_NETWORK))*(100 div (($yval_min)-($yval_max)))))}" fill="tan" stroke="black"/>   
             <rect x="{$margin_left+$bar_width*(position()-1)}" y="{round(($graph_height)-($margin_bottom)-((($yval_min)-(descendant::C_USER_IO))*(100 div (($yval_min)-($yval_max)))))}" width="{$bar_width}" height="{round((((descendant::C_NETWORK)-(C_USER_IO))*(100 div (($yval_min)-($yval_max)))))}" fill="royalblue" stroke="black"/>   
             <rect x="{$margin_left+$bar_width*(position()-1)}" y="{round(($graph_height)-($margin_bottom)-((($yval_min)-(descendant::C_SYSTEM_IO))*(100 div (($yval_min)-($yval_max)))))}" width="{$bar_width}" height="{round((((descendant::C_USER_IO)-(C_SYSTEM_IO))*(100 div (($yval_min)-($yval_max)))))}" fill="skyblue" stroke="black"/>   
             <rect x="{$margin_left+$bar_width*(position()-1)}" y="{round(($graph_height)-($margin_bottom)-((($yval_min)-(descendant::C_SCHEDULER))*(100 div (($yval_min)-($yval_max)))))}" width="{$bar_width}" height="{round((((descendant::C_SYSTEM_IO)-(C_SCHEDULER))*(100 div (($yval_min)-($yval_max)))))}" fill="lightcyan" stroke="black"/>   
             <rect x="{$margin_left+$bar_width*(position()-1)}" y="{round(($graph_height)-($margin_bottom)-((($yval_min)-(descendant::C_CLUSTER))*(100 div (($yval_min)-($yval_max)))))}" width="{$bar_width}" height="{round((((descendant::C_SCHEDULER)-(C_CLUSTER))*(100 div (($yval_min)-($yval_max)))))}" fill="lightgray" stroke="black"/>   
             <rect x="{$margin_left+$bar_width*(position()-1)}" y="{round(($graph_height)-($margin_bottom)-((($yval_min)-(descendant::C_QUEUEING))*(100 div (($yval_min)-($yval_max)))))}" width="{$bar_width}" height="{round((((descendant::C_CLUSTER)-(C_QUEUEING))*(100 div (($yval_min)-($yval_max)))))}" fill="bisque" stroke="black"/> 
           </xsl:for-each>
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+8}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">Other</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+3}" width="{10}" height="{6}" fill="hotpink" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+16}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">Application</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+11}" width="{10}" height="{6}" fill="indianred" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+24}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">Configuration</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+19}" width="{10}" height="{6}" fill="olive" stroke="black"/>   
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+32}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">Administrative</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+27}" width="{10}" height="{6}" fill="gray" stroke="black"/>   
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+40}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">Concurrency</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+35}" width="{10}" height="{6}" fill="sienna" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+48}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">Commit</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+43}" width="{10}" height="{6}" fill="orange" stroke="black"/>'
           ) 
    || 
    TO_CLOB(
          '<text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+56}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">Network</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+51}" width="{10}" height="{6}" fill="tan" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+64}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">User IO</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+59}" width="{10}" height="{6}" fill="royalblue" stroke="black"/>  
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+72}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">System IO</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+67}" width="{10}" height="{6}" fill="skyblue" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+80}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">Scheduler</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+75}" width="{10}" height="{6}" fill="lightcyan" stroke="black"/>
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+88}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">Cluster</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+83}" width="{10}" height="{6}" fill="lightgray" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+96}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">Queueing</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+91}" width="{10}" height="{6}" fill="bisque" stroke="black"/>                                                  
         </svg>
       </xsl:template>
     </xsl:stylesheet>'
           )
   )
   ) 
FROM dual;

SPOOL OFF
SET HEADING ON

SET VERIFY   ON
SET FEEDBACK ON

Result:

generate_svg_16i

Remark:

  • The system variables LONGCHUNKSIZE and LONG have been increased to 100000.
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: