Oracle database experiences

Oracle database blog

Category Archives: Graphic

Generating SVG graphics with SQL*Plus – Part XXVI – Stacked area graph – Session Activity – Light Sampling Sessions – Database Group splitting

Scope

Following the previous post, we will now consolidate the two database activities and generate a graph like in the part XXII. To achieve that, we will create a private database link and three views.
We will make the assumption that the CDB$ROOT container database has a 2 seconds sampling period interval and that the PDB1 pluggable database has a 5 seconds sampling period interval.

CDB$ROOT Database Link

Let’s grant the following system privilege to the common user C##LSS:

@> connect / as sysdba
Connected.
SYS@orcl> show con_name;

CON_NAME
------------------------------
CDB$ROOT
SYS@orcl> GRANT CREATE DATABASE LINK TO C##LSS;

Grant succeeded.

The common User C##LSS can now create private database links. Let’s create a private database link on the PDB1 pluggable database:

@> connect c##lss@orcl
Enter password:
Connected.
C##LSS@orcl> show con_name;

CON_NAME
------------------------------
CDB$ROOT
C##LSS@orcl> CREATE DATABASE LINK "DB_GRP_ELT2" CONNECT TO LSS IDENTIFIED by lss USING 'pdb1';

Database link created.

Let’s revoke the following system privilege from C##LSS:

SYS@orcl> REVOKE CREATE DATABASE LINK FROM C##LSS;

Revoke succeeded.

Let’s try the database link:

C##LSS@orcl> SELECT COUNT(*) FROM LSS$_SAMPLING_SESSION@DB_GRP_ELT2;

  COUNT(*)
----------
      1066

1 row selected.

The base view will be derived from the view v$cdb_pdb_aas_lss, but the inner query of this view will be a consolidation of the first and the second database.

View v$db_grp_elt1_aas_lss

This view is linked to the CDB$ROOT container database:

CREATE OR REPLACE VIEW v$db_grp_elt1_aas_lss
AS   
SELECT TO_CHAR(sample_time,'YYYYMMDDHH24MI') sample_yyyymmddhhmi,
       element_id,
       30 nb_samples,
       COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),-1,1)) count_cpu,
       COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),0,1,1,1,2,1,3,1,4,1,5,1,7,1,8,1,9,1,10,1,11,1,12,1)) count_wait
FROM lss$_sampling_session
WHERE con_id IN (0,1)
  AND inst_id = 1
GROUP BY element_id,
TO_CHAR(sample_time,'YYYYMMDDHH24MI');

To measure only the activity of the CDB$ROOT database, there is a restriction on the con_id column.

View v$db_grp_elt2_aas_lss

This view is linked to the PDB1 pluggable database:

CREATE OR REPLACE VIEW v$db_grp_elt2_aas_lss
AS   
SELECT TO_CHAR(sample_time,'YYYYMMDDHH24MI') sample_yyyymmddhhmi,
       element_id,
       12 nb_samples, 
       COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),-1,1)) count_cpu,
       COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),0,1,1,1,2,1,3,1,4,1,5,1,7,1,8,1,9,1,10,1,11,1,12,1)) count_wait
FROM lss$_sampling_session@db_grp_elt2
WHERE inst_id = 1
GROUP BY element_id,
TO_CHAR(sample_time,'YYYYMMDDHH24MI');

Finally the main view is defined as follow:

View v$db_group1_aas_lss

CREATE OR REPLACE VIEW v$db_group1_aas_lss
AS 
SELECT sample_yyyymmddhhmi,
       SUBSTR(sample_yyyymmddhhmi,9,2) || ':' || SUBSTR(sample_yyyymmddhhmi,11,2)                                        BEGIN_TIME,
       aas_cpu1                                                                                                          C_ELT1_CPU,
       aas_cpu1+aas_wait1                                                                                                C_ELT1_WAIT,
       aas_cpu1+aas_wait1+aas_cpu2                                                                                       C_ELT2_CPU,
       aas_cpu1+aas_wait1+aas_cpu2+aas_wait2                                                                             C_ELT2_WAIT,
       aas_cpu1+aas_wait1+aas_cpu2+aas_wait2+aas_cpu3                                                                    C_ELT3_CPU,
       aas_cpu1+aas_wait1+aas_cpu2+aas_wait2+aas_cpu3+aas_wait3                                                          C_ELT3_WAIT,
       aas_cpu1+aas_wait1+aas_cpu2+aas_wait2+aas_cpu3+aas_wait3+aas_cpu4                                                 C_ELT4_CPU,
       aas_cpu1+aas_wait1+aas_cpu2+aas_wait2+aas_cpu3+aas_wait3+aas_cpu4+aas_wait4                                       C_ELT4_WAIT,
       aas_cpu1+aas_wait1+aas_cpu2+aas_wait2+aas_cpu3+aas_wait3+aas_cpu4+aas_wait4+aas_cpu5                              C_ELT5_CPU,
       aas_cpu1+aas_wait1+aas_cpu2+aas_wait2+aas_cpu3+aas_wait3+aas_cpu4+aas_wait4+aas_cpu5+aas_wait5                    C_ELT5_WAIT,
       aas_cpu1+aas_wait1+aas_cpu2+aas_wait2+aas_cpu3+aas_wait3+aas_cpu4+aas_wait4+aas_cpu5+aas_wait5+aas_cpu6           C_ELT6_CPU,
       aas_cpu1+aas_wait1+aas_cpu2+aas_wait2+aas_cpu3+aas_wait3+aas_cpu4+aas_wait4+aas_cpu5+aas_wait5+aas_cpu6+aas_wait6 C_ELT6_WAIT,
       MAX(CEIL(aas_cpu1+aas_wait1+aas_cpu2+aas_wait2+aas_cpu3+aas_wait3+aas_cpu4+aas_wait4+aas_cpu5+aas_wait5+aas_cpu6+aas_wait6)) OVER() MAX_CONT_AAS
FROM 
   (SELECT NVL(co_base_qry.sample_yyyymmddhhmi,time_window.start_time) sample_yyyymmddhhmi,
           NVL(co_base_qry.sum_aas_cpu1,0)   aas_cpu1,
           NVL(co_base_qry.sum_aas_wait1,0)  aas_wait1,
           NVL(co_base_qry.sum_aas_cpu2,0)   aas_cpu2,
           NVL(co_base_qry.sum_aas_wait2,0)  aas_wait2,
           NVL(co_base_qry.sum_aas_cpu3,0)   aas_cpu3,
           NVL(co_base_qry.sum_aas_wait3,0)  aas_wait3,
           NVL(co_base_qry.sum_aas_cpu4,0)   aas_cpu4,
           NVL(co_base_qry.sum_aas_wait4,0)  aas_wait4,
           NVL(co_base_qry.sum_aas_cpu5,0)   aas_cpu5,
           NVL(co_base_qry.sum_aas_wait5,0)  aas_wait5,
           NVL(co_base_qry.sum_aas_cpu6,0)   aas_cpu6,
           NVL(co_base_qry.sum_aas_wait6,0)  aas_wait6
    FROM 
       (SELECT TO_CHAR(SYSDATE - (LEVEL/24/60),'YYYYMMDDHH24MI') start_time
        FROM DUAL 
        CONNECT BY LEVEL <= 61
       ) time_window
    LEFT OUTER JOIN 
       (SELECT sample_yyyymmddhhmi,
               SUM(aas_cpu1)  sum_aas_cpu1,
               SUM(aas_wait1) sum_aas_wait1,
               SUM(aas_cpu2)  sum_aas_cpu2,
               SUM(aas_wait2) sum_aas_wait2,
               SUM(aas_cpu3)  sum_aas_cpu3,
               SUM(aas_wait3) sum_aas_wait3,
               SUM(aas_cpu4)  sum_aas_cpu4,
               SUM(aas_wait4) sum_aas_wait4,
               SUM(aas_cpu5)  sum_aas_cpu5,
               SUM(aas_wait5) sum_aas_wait5,
               SUM(aas_cpu6)  sum_aas_cpu6,
               SUM(aas_wait6) sum_aas_wait6
        FROM 
           (SELECT sample_yyyymmddhhmi,
                   CASE element_id
                      WHEN 1 THEN TRUNC(count_cpu/(nb_samples),3)
                      ELSE 0
                   END aas_cpu1,
                   CASE element_id
                      WHEN 1 THEN TRUNC(count_wait/(nb_samples),3)
                      ELSE 0
                   END aas_wait1,
                   CASE element_id
                      WHEN 2 THEN TRUNC(count_cpu/(nb_samples),3)
                      ELSE 0
                   END aas_cpu2,
                   CASE element_id
                      WHEN 2 THEN TRUNC(count_wait/(nb_samples),3)
                      ELSE 0
                   END aas_wait2,
                   CASE element_id
                      WHEN 3 THEN TRUNC(count_cpu/(nb_samples),3)
                      ELSE 0
                   END aas_cpu3,
                   CASE element_id
                      WHEN 3 THEN TRUNC(count_wait/(nb_samples),3)
                      ELSE 0
                   END aas_wait3,
                   CASE element_id
                      WHEN 4 THEN TRUNC(count_cpu/(nb_samples),3)
                      ELSE 0
                   END aas_cpu4,
                   CASE element_id
                      WHEN 4 THEN TRUNC(count_wait/(nb_samples),3)
                      ELSE 0
                   END aas_wait4,
                   CASE element_id
                      WHEN 5 THEN TRUNC(count_cpu/(nb_samples),3)
                      ELSE 0
                   END aas_cpu5,
                   CASE element_id
                      WHEN 5 THEN TRUNC(count_wait/(nb_samples),3)
                      ELSE 0
                   END aas_wait5,
                   CASE element_id
                      WHEN 6 THEN TRUNC(count_cpu/(nb_samples),3)
                      ELSE 0
                   END aas_cpu6,
                   CASE element_id
                      WHEN 6 THEN TRUNC(count_wait/(nb_samples),3)
                      ELSE 0
                   END aas_wait6
            FROM 
               (SELECT sample_yyyymmddhhmi,
                       element_id,
                       nb_samples,
                       count_cpu,
                       count_wait
                FROM v$db_grp_elt1_aas_lss
                UNION ALL
                SELECT sample_yyyymmddhhmi,
                       element_id,
                       nb_samples,
                       count_cpu,
                       count_wait
                FROM v$db_grp_elt2_aas_lss
                )
           ) GROUP BY sample_yyyymmddhhmi
       ) co_base_qry
      ON time_window.start_time=co_base_qry.sample_yyyymmddhhmi
   );

Remark:

  • If the local time of the second database is not the same than the local time of the first database, the view v$db_grp_elt2_aas_lss might be modified in order to have a synchronized sample_yyyymmddhhmi column value between the two databases.

Modified source query

We will use the query defined in the part XXII as a starting point. We will modify the source query as follow:

        SELECT BEGIN_TIME,
               C_ELT1_CPU,
               C_ELT1_WAIT,
               C_ELT2_CPU,
               C_ELT2_WAIT,
               C_ELT3_CPU,
               C_ELT3_WAIT,
               C_ELT4_CPU,
               C_ELT4_WAIT,
               C_ELT5_CPU,
               C_ELT5_WAIT,
               C_ELT6_CPU,
               C_ELT6_WAIT,
               MAX_CONT_AAS
        FROM v$db_group1_aas_lss
        ORDER BY sample_yyyymmddhhmi

XSLT processing

We will use the query defined in the part XXII as a starting point with the following modifications:

  • The differents “for-each” “ROWSET/ROW/C_CONT0_CPU” to “ROWSET/ROW/C_CONT5_WAIT” have been replaced by “ROWSET/ROW/C_ELT1_CPU” to “ROWSET/ROW/C_ELT6_WAIT”,
  • The “cpu_count” processing has been removed.

XSLT variables

The variable “graph_name” is set to ‘LSS Active Sessions – Waiting + Working – Database Group splitting’.

Modified query

SET LINESIZE      2000
SET LONGCHUNKSIZE 30000
SET LONG          30000

SET FEEDBACK OFF
SET VERIFY   OFF
SET PAGESIZE 0

SET HEADING OFF

SPOOL generate_svg_26c.svg

SELECT XMLTRANSFORM
   (DBMS_XMLGEN.GETXMLTYPE
      ('SELECT BEGIN_TIME,
               C_ELT1_CPU,
               C_ELT1_WAIT,
               C_ELT2_CPU,
               C_ELT2_WAIT,
               C_ELT3_CPU,
               C_ELT3_WAIT,
               C_ELT4_CPU,
               C_ELT4_WAIT,
               C_ELT5_CPU,
               C_ELT5_WAIT,
               C_ELT6_CPU,
               C_ELT6_WAIT,
               MAX_CONT_AAS
        FROM v$db_group1_aas_lss
        ORDER BY sample_yyyymmddhhmi')
,      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">10</xsl:variable>
     <xsl:variable name="graph_width"><xsl:value-of select="600+$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">LSS Active Sessions - Waiting + Working - Database Group splitting</xsl:variable>
     <xsl:variable name="graph_unit">Session Count</xsl:variable>
     <xsl:variable name="yval_max"><xsl:value-of select="/descendant::MAX_CONT_AAS[position()=1]"/></xsl:variable>
     <xsl:variable name="yval_min">0</xsl:variable>
       <xsl:template match="/">'
           )
    || 
    TO_CLOB(
         '<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)-24}" y="{($graph_height)-($margin_bottom)-2}"   style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="format-number(($yval_min),''00.00'')"/></text>
           <text x="{($margin_left)-24}" y="{($graph_height)-($margin_bottom)-25}"  style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="format-number((($yval_min)+(1*(($yval_max)-($yval_min)) div 4)),''00.00'')"/></text>
           <text x="{($margin_left)-24}" y="{($graph_height)-($margin_bottom)-50}"  style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="format-number((($yval_min)+((($yval_max)-($yval_min)) div 2)),''00.00'')"/></text>
           <text x="{($margin_left)-24}" y="{($graph_height)-($margin_bottom)-75}"  style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="format-number((($yval_min)+(3*(($yval_max)-($yval_min)) div 4)),''00.00'')"/></text>
           <text x="{($margin_left)-24}" y="{($graph_height)-($margin_bottom)-100}" style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="format-number(($yval_max),''00.00'')"/></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:otherwise>
                 <line x1="{($margin_left)+($bar_width*(position()-1))}" y1="{($graph_height)-($margin_bottom)+3}" x2="{($margin_left)+($bar_width*(position()-1))}" y2="{($graph_height)-($margin_bottom)+0}" style="stroke:lightblue;stroke-width:1" /> 
               </xsl:otherwise>
             </xsl:choose>    
           </xsl:for-each>
           <xsl:variable name="v_path0">
             <xsl:for-each select="ROWSET/ROW/C_ELT1_CPU">
               <xsl:variable name="x_val0">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val0">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val0,'','',$y_val0,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path0} {$x_val0},{($graph_height)-($margin_bottom)} {$margin_left},{($graph_height)-($margin_bottom)}" style="fill:aquamarine;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path1">
             <xsl:for-each select="ROWSET/ROW/C_ELT1_WAIT">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val1">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val1">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val1,'','',$y_val1,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path0}{$v_path1}" style="fill:steelblue;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path2">
             <xsl:for-each select="ROWSET/ROW/C_ELT2_CPU">
               <xsl:variable name="x_val2">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val2">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val2,'','',$y_val2,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path1}{$v_path2}" style="fill:darkkhaki;stroke:none;stroke-width:1" />'
           )
    ||
    TO_CLOB(
          '<xsl:variable name="v_path3">
             <xsl:for-each select="ROWSET/ROW/C_ELT2_WAIT">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val3">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val3">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val3,'','',$y_val3,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path2}{$v_path3}" style="fill:gold;stroke:none;stroke-width:1" />'
           )
    ||
    TO_CLOB(
          '<xsl:variable name="v_path4">
             <xsl:for-each select="ROWSET/ROW/C_ELT3_CPU">
               <xsl:variable name="x_val4">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val4">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val4,'','',$y_val4,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path3}{$v_path4}" style="fill:lightsalmon;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path5">
             <xsl:for-each select="ROWSET/ROW/C_ELT3_WAIT">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val5">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val5">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val5,'','',$y_val5,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path4}{$v_path5}" style="fill:orangered;stroke:none;stroke-width:1" />'
           )
    ||
    TO_CLOB(
          '<xsl:variable name="v_path6">
             <xsl:for-each select="ROWSET/ROW/C_ELT4_CPU">
               <xsl:variable name="x_val6">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val6">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val6,'','',$y_val6,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path5}{$v_path6}" style="fill:plum;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path7">
             <xsl:for-each select="ROWSET/ROW/C_ELT4_WAIT">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val7">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val7">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val7,'','',$y_val7,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path6}{$v_path7}" style="fill:magenta;stroke:none;stroke-width:1" /><xsl:variable name="v_path8">
             <xsl:for-each select="ROWSET/ROW/C_ELT5_CPU">
               <xsl:variable name="x_val8">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val8">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val8,'','',$y_val8,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path7}{$v_path8}" style="fill:skyblue;stroke:none;stroke-width:1" />'
           )
    ||
    TO_CLOB(
          '<xsl:variable name="v_path9">
             <xsl:for-each select="ROWSET/ROW/C_ELT5_WAIT">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val9">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val9">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val9,'','',$y_val9,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path8}{$v_path9}" style="fill:dodgerblue;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path10">
             <xsl:for-each select="ROWSET/ROW/C_ELT6_CPU">
               <xsl:variable name="x_val10">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val10">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val10,'','',$y_val10,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path9}{$v_path10}" style="fill:greenyellow;stroke:none;stroke-width:1" />'
           )
    ||
    TO_CLOB(
          '<xsl:variable name="v_path11">
             <xsl:for-each select="ROWSET/ROW/C_ELT6_WAIT">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val11">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val11">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val11,'','',$y_val11,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path10}{$v_path11}" style="fill:limegreen;stroke:none;stroke-width:1" />
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+5}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">ELT1 CPU</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+0}" width="{10}" height="{6}" fill="aquamarine" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+13}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">ELT1 Wait</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+8}" width="{10}" height="{6}" fill="steelblue" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+21}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">ELT2 CPU</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+16}" width="{10}" height="{6}" fill="darkkhaki" stroke="black"/>   
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+29}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">ELT2 Wait</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+24}" width="{10}" height="{6}" fill="gold" stroke="black"/>   
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+37}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">ELT3 CPU</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+32}" width="{10}" height="{6}" fill="lightsalmon" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+45}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">ELT3 Wait</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+40}" width="{10}" height="{6}" fill="orangered" stroke="black"/>'
           ) 
    || 
    TO_CLOB(
          '<text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+53}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">ELT4 CPU</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+48}" width="{10}" height="{6}" fill="plum" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+61}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">ELT4 Wait</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+56}" width="{10}" height="{6}" fill="magenta" stroke="black"/>
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+69}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">ELT5 CPU</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+64}" width="{10}" height="{6}" fill="skyblue" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+77}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">ELT5 Wait</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+72}" width="{10}" height="{6}" fill="dodgerblue" stroke="black"/>
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+85}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">ELT6 CPU</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+80}" width="{10}" height="{6}" fill="greenyellow" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+93}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">ELT6 Wait</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+88}" width="{10}" height="{6}" fill="limegreen" stroke="black"/> 
         </svg>
       </xsl:template>
     </xsl:stylesheet>'
           )
   )
   ) 
FROM dual;

SPOOL OFF
SET HEADING ON

SET VERIFY   ON
SET FEEDBACK ON

Result:

generate_svg_26c

Result with the query of part XXII on the same period:

generate_svg_26c_22h

Remarks:

  • The general shape of the two graphs is similar,
  • The query has been executed from the CDB$ROOT container by the C##LSS common user,
  • The views v$db_grp_elt1_aas_lss, v$db_grp_elt2_aas_lss and v$db_group1_aas_lss are created from the CDB$ROOT container in the C##LSS schema,
  • You could consolidate more databases by creating views of the type v$db_grp_eltY_aas_lss and by modifying the view v$db_group1_aas_lss.

Generating SVG graphics with SQL*Plus – Part XXV – Stacked area graph – Session Activity – Light Sampling Sessions – Update

Scope

In this post we will focus on tracking session activity at CDB/PDB level and on increasing the accuracy of the graph. The previous post displays the consolidated session id at the instance level. If we want to track a session at the CDB/PDB level we need:

  • A session id,
  • A serial#,
  • A container id.

Function get_current_session

We will slightly modify the function get_current_session in order to get the triplet ‘[session_id],[serial#],[con_id]’:

CREATE OR REPLACE FUNCTION get_current_session RETURN VARCHAR2
AS 
   v_param_value lss$parameter.parameter_value%TYPE;
BEGIN

   SELECT parameter_value
   INTO v_param_value
   FROM lss$parameter
   WHERE parameter_name = 'current_session';
   
   RETURN v_param_value;
   
   EXCEPTION
      WHEN TOO_MANY_ROWS THEN
         RETURN '<UNKNOWN>';
      WHEN NO_DATA_FOUND THEN
         RETURN '<UNKNOWN>';
      WHEN OTHERS THEN
         RAISE;
         
END get_current_session;

Basically the triplet will be stored in the table lss$parameter as a string.

Increase graph accuracy

Instead of counting the events on a period of time of one minute we will count them on a period of time of 30 seconds. We will create a new view v$session_activity30s_lss in order to display the session activity every 30 seconds. The starting point will be the view v$session_activity_lss.

View creation – Step 1

The differences with the previous post are:

WITH session_events AS
   (
   SELECT event,
          COUNT(*) count_event, 
          RANK() OVER (ORDER BY COUNT(*) DESC, EVENT) rank_event 
   FROM lss$_sampling_session
   WHERE TO_CHAR(sid) || ',' || TO_CHAR(serial#) || ',' || TO_CHAR(con_id) = get_current_session
     AND sample_time >= SYSDATE -(1/24) 
     AND session_state <> 'C'
   GROUP BY event
   ORDER BY count_event DESC
   FETCH FIRST 12 ROWS ONLY
   )

The session identifier is now ‘[session_id],[serial#],[con_id]’.

View creation – Step 2

The differences with the previous post are:

            SELECT TO_CHAR(sample_time,'YYYYMMDDHH24MI') || TO_CHAR(TRUNC(TO_NUMBER(TO_CHAR(sample_time,'SS'))/30)) sample_yyyymmddhhmi30s,
                   MAX(sample_id) - MIN(sample_id) nb_samples,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),-1,1)) count_event0,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),1,1))  count_event1,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),2,1))  count_event2,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),3,1))  count_event3,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),4,1))  count_event4,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),5,1))  count_event5,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),6,1))  count_event6,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),7,1))  count_event7,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),8,1))  count_event8,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),9,1))  count_event9,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),10,1)) count_event10,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),11,1)) count_event11,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),12,1)) count_event12,
                   'cpu'    event_name0,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),1,sess_event.event))  event_name1,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),2,sess_event.event))  event_name2,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),3,sess_event.event))  event_name3,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),4,sess_event.event))  event_name4,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),5,sess_event.event))  event_name5,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),6,sess_event.event))  event_name6,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),7,sess_event.event))  event_name7,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),8,sess_event.event))  event_name8,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),9,sess_event.event))  event_name9,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),10,sess_event.event)) event_name10,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),11,sess_event.event)) event_name11,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),12,sess_event.event)) event_name12
            FROM lss$_sampling_session lss
            LEFT OUTER JOIN session_events sess_event
              ON sess_event.event = lss.event
            WHERE TO_CHAR(lss.sid) || ',' || TO_CHAR(lss.serial#) || ',' || TO_CHAR(lss.con_id) = get_current_session
            GROUP BY TO_CHAR(sample_time,'YYYYMMDDHH24MI') || TO_CHAR(TRUNC(TO_NUMBER(TO_CHAR(sample_time,'SS'))/30))

The session identifier is now ‘[session_id],[serial#],[con_id]’. In order to count the events every 30 seconds, we will define the first 30 seconds of a minute as “0” and the last 30 seconds of a minute as “1”. The time dimension is now called sample_yyyymmddhhmi30s.

View creation – Step 3

The differences with the previous post are:

        SELECT NVL(co_base_qry.sample_yyyymmddhhmi30s,time_window.start_time) sample_yyyymmddhhmi30s,
               NVL(co_base_qry.nb_samples,1)    nb_samples,
               NVL(co_base_qry.count_event0,0)  count_event0,
               NVL(co_base_qry.count_event1,0)  count_event1,
               NVL(co_base_qry.count_event2,0)  count_event2,
               NVL(co_base_qry.count_event3,0)  count_event3,
               NVL(co_base_qry.count_event4,0)  count_event4,
               NVL(co_base_qry.count_event5,0)  count_event5,
               NVL(co_base_qry.count_event6,0)  count_event6,
               NVL(co_base_qry.count_event7,0)  count_event7,
               NVL(co_base_qry.count_event8,0)  count_event8,
               NVL(co_base_qry.count_event9,0)  count_event9,
               NVL(co_base_qry.count_event10,0) count_event10,
               NVL(co_base_qry.count_event11,0) count_event11,
               NVL(co_base_qry.count_event12,0) count_event12,
               co_base_qry.event_name0,
               co_base_qry.event_name1,
               co_base_qry.event_name2,
               co_base_qry.event_name3,
               co_base_qry.event_name4,
               co_base_qry.event_name5,
               co_base_qry.event_name6,
               co_base_qry.event_name7,
               co_base_qry.event_name8,
               co_base_qry.event_name9,
               co_base_qry.event_name10,
               co_base_qry.event_name11,
               co_base_qry.event_name12
        FROM
           (SELECT TO_CHAR(SYSDATE - ((LEVEL*30)/24/60/60),'YYYYMMDDHH24MI') || TO_CHAR(TRUNC(TO_NUMBER(TO_CHAR(SYSDATE - ((LEVEL*30)/24/60/60),'SS'))/30)) start_time
            FROM DUAL 
            CONNECT BY LEVEL <= 122
            ) time_window
        LEFT OUTER JOIN 
           (SELECT TO_CHAR(sample_time,'YYYYMMDDHH24MI') || TO_CHAR(TRUNC(TO_NUMBER(TO_CHAR(sample_time,'SS'))/30)) sample_yyyymmddhhmi30s,
                   MAX(sample_id) - MIN(sample_id) nb_samples,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),-1,1)) count_event0,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),1,1))  count_event1,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),2,1))  count_event2,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),3,1))  count_event3,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),4,1))  count_event4,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),5,1))  count_event5,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),6,1))  count_event6,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),7,1))  count_event7,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),8,1))  count_event8,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),9,1))  count_event9,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),10,1)) count_event10,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),11,1)) count_event11,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),12,1)) count_event12,
                   'cpu'    event_name0,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),1,sess_event.event))  event_name1,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),2,sess_event.event))  event_name2,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),3,sess_event.event))  event_name3,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),4,sess_event.event))  event_name4,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),5,sess_event.event))  event_name5,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),6,sess_event.event))  event_name6,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),7,sess_event.event))  event_name7,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),8,sess_event.event))  event_name8,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),9,sess_event.event))  event_name9,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),10,sess_event.event)) event_name10,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),11,sess_event.event)) event_name11,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),12,sess_event.event)) event_name12
            FROM lss$_sampling_session lss
            LEFT OUTER JOIN session_events sess_event
              ON sess_event.event = lss.event
            WHERE TO_CHAR(lss.sid) || ',' || TO_CHAR(lss.serial#) || ',' || TO_CHAR(lss.con_id) = get_current_session
            GROUP BY TO_CHAR(sample_time,'YYYYMMDDHH24MI') || TO_CHAR(TRUNC(TO_NUMBER(TO_CHAR(sample_time,'SS'))/30))
            ) co_base_qry
          ON time_window.start_time=co_base_qry.sample_yyyymmddhhmi30s

The time_windows query has changed in order to have 30 second intervals.

View creation – Step 4

The differences with the previous post are:

    SELECT sample_yyyymmddhhmi30s,
           TRUNC((count_event0/(nb_samples+1)),3)  avge1,  
           TRUNC((count_event1/(nb_samples+1)),3)  avge2,  
           TRUNC((count_event2/(nb_samples+1)),3)  avge3, 
           TRUNC((count_event3/(nb_samples+1)),3)  avge4,  
           TRUNC((count_event4/(nb_samples+1)),3)  avge5,  
           TRUNC((count_event5/(nb_samples+1)),3)  avge6,  
           TRUNC((count_event6/(nb_samples+1)),3)  avge7,  
           TRUNC((count_event7/(nb_samples+1)),3)  avge8,  
           TRUNC((count_event8/(nb_samples+1)),3)  avge9,  
           TRUNC((count_event9/(nb_samples+1)),3)  avge10, 
           TRUNC((count_event10/(nb_samples+1)),3) avge11, 
           TRUNC((count_event11/(nb_samples+1)),3) avge12, 
           TRUNC((count_event12/(nb_samples+1)),3) avge13,  
           event_name0,
           event_name1,
           event_name2,
           event_name3,
           event_name4,
           event_name5,
           event_name6,
           event_name7,
           event_name8,
           event_name9,
           event_name10,
           event_name11,
           event_name12
    FROM 
       (SELECT NVL(co_base_qry.sample_yyyymmddhhmi30s,time_window.start_time) sample_yyyymmddhhmi30s,
               NVL(co_base_qry.nb_samples,1)    nb_samples,
               NVL(co_base_qry.count_event0,0)  count_event0,
               NVL(co_base_qry.count_event1,0)  count_event1,
               NVL(co_base_qry.count_event2,0)  count_event2,
               NVL(co_base_qry.count_event3,0)  count_event3,
               NVL(co_base_qry.count_event4,0)  count_event4,
               NVL(co_base_qry.count_event5,0)  count_event5,
               NVL(co_base_qry.count_event6,0)  count_event6,
               NVL(co_base_qry.count_event7,0)  count_event7,
               NVL(co_base_qry.count_event8,0)  count_event8,
               NVL(co_base_qry.count_event9,0)  count_event9,
               NVL(co_base_qry.count_event10,0) count_event10,
               NVL(co_base_qry.count_event11,0) count_event11,
               NVL(co_base_qry.count_event12,0) count_event12,
               co_base_qry.event_name0,
               co_base_qry.event_name1,
               co_base_qry.event_name2,
               co_base_qry.event_name3,
               co_base_qry.event_name4,
               co_base_qry.event_name5,
               co_base_qry.event_name6,
               co_base_qry.event_name7,
               co_base_qry.event_name8,
               co_base_qry.event_name9,
               co_base_qry.event_name10,
               co_base_qry.event_name11,
               co_base_qry.event_name12
        FROM
           (SELECT TO_CHAR(SYSDATE - ((LEVEL*30)/24/60/60),'YYYYMMDDHH24MI') || TO_CHAR(TRUNC(TO_NUMBER(TO_CHAR(SYSDATE - ((LEVEL*30)/24/60/60),'SS'))/30)) start_time
            FROM DUAL 
            CONNECT BY LEVEL <= 122
            ) time_window
        LEFT OUTER JOIN 
           (SELECT TO_CHAR(sample_time,'YYYYMMDDHH24MI') || TO_CHAR(TRUNC(TO_NUMBER(TO_CHAR(sample_time,'SS'))/30)) sample_yyyymmddhhmi30s,
                   MAX(sample_id) - MIN(sample_id) nb_samples,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),-1,1)) count_event0,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),1,1))  count_event1,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),2,1))  count_event2,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),3,1))  count_event3,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),4,1))  count_event4,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),5,1))  count_event5,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),6,1))  count_event6,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),7,1))  count_event7,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),8,1))  count_event8,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),9,1))  count_event9,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),10,1)) count_event10,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),11,1)) count_event11,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),12,1)) count_event12,
                   'cpu'    event_name0,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),1,sess_event.event))  event_name1,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),2,sess_event.event))  event_name2,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),3,sess_event.event))  event_name3,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),4,sess_event.event))  event_name4,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),5,sess_event.event))  event_name5,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),6,sess_event.event))  event_name6,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),7,sess_event.event))  event_name7,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),8,sess_event.event))  event_name8,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),9,sess_event.event))  event_name9,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),10,sess_event.event)) event_name10,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),11,sess_event.event)) event_name11,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),12,sess_event.event)) event_name12
            FROM lss$_sampling_session lss
            LEFT OUTER JOIN session_events sess_event
              ON sess_event.event = lss.event
            WHERE TO_CHAR(lss.sid) || ',' || TO_CHAR(lss.serial#) || ',' || TO_CHAR(lss.con_id) = get_current_session
            GROUP BY TO_CHAR(sample_time,'YYYYMMDDHH24MI') || TO_CHAR(TRUNC(TO_NUMBER(TO_CHAR(sample_time,'SS'))/30))
            ) co_base_qry
          ON time_window.start_time=co_base_qry.sample_yyyymmddhhmi30s
       )

View creation – Step 5

The differences with the previous post are:

CREATE OR REPLACE VIEW v$session_activity30s_lss
AS
WITH session_events AS
   (
   SELECT event,
          COUNT(*) count_event, 
          RANK() OVER (ORDER BY COUNT(*) DESC, EVENT) rank_event 
   FROM lss$_sampling_session
   WHERE TO_CHAR(sid) || ',' || TO_CHAR(serial#) || ',' || TO_CHAR(con_id) = get_current_session
     AND sample_time >= SYSDATE -(1/24) 
     AND session_state <> 'C'
   GROUP BY event
   ORDER BY count_event DESC
   FETCH FIRST 12 ROWS ONLY
   )
SELECT sample_yyyymmddhhmi30s,
       SUBSTR(sample_yyyymmddhhmi30s,9,2) || ':' || SUBSTR(sample_yyyymmddhhmi30s,11,2) BEGIN_TIME,
       avge1                                                                             C_EVENT0,
       avge1+avge2                                                                       C_EVENT1,
       avge1+avge2+avge3                                                                 C_EVENT2,
       avge1+avge2+avge3+avge4                                                           C_EVENT3,
       avge1+avge2+avge3+avge4+avge5                                                     C_EVENT4,
       avge1+avge2+avge3+avge4+avge5+avge6                                               C_EVENT5,
       avge1+avge2+avge3+avge4+avge5+avge6+avge7                                         C_EVENT6,
       avge1+avge2+avge3+avge4+avge5+avge6+avge7+avge8                                   C_EVENT7,
       avge1+avge2+avge3+avge4+avge5+avge6+avge7+avge8+avge9                             C_EVENT8,
       avge1+avge2+avge3+avge4+avge5+avge6+avge7+avge8+avge9+avge10                      C_EVENT9,
       avge1+avge2+avge3+avge4+avge5+avge6+avge7+avge8+avge9+avge10+avge11               C_EVENT10,
       avge1+avge2+avge3+avge4+avge5+avge6+avge7+avge8+avge9+avge10+avge11+avge12        C_EVENT11,
       avge1+avge2+avge3+avge4+avge5+avge6+avge7+avge8+avge9+avge10+avge11+avge12+avge13 C_EVENT12,
       MAX(CEIL(avge1+avge2+avge3+avge4+avge5+avge6+avge7+avge8+avge9+avge10+avge11+avge12+avge13)) OVER() MAX_EVENT,
       (SELECT get_current_session FROM DUAL) session_id,
       MAX(event_name0)  OVER() EVENT_NAME0,
       MAX(event_name1)  OVER() EVENT_NAME1,
       MAX(event_name2)  OVER() EVENT_NAME2,
       MAX(event_name3)  OVER() EVENT_NAME3,
       MAX(event_name4)  OVER() EVENT_NAME4,
       MAX(event_name5)  OVER() EVENT_NAME5,
       MAX(event_name6)  OVER() EVENT_NAME6,
       MAX(event_name7)  OVER() EVENT_NAME7,
       MAX(event_name8)  OVER() EVENT_NAME8,
       MAX(event_name9)  OVER() EVENT_NAME9,
       MAX(event_name10) OVER() EVENT_NAME10,
       MAX(event_name11) OVER() EVENT_NAME11,
       MAX(event_name12) OVER() EVENT_NAME12
FROM
   (SELECT sample_yyyymmddhhmi30s,
           TRUNC((count_event0/(nb_samples+1)),3)  avge1,  
           TRUNC((count_event1/(nb_samples+1)),3)  avge2,  
           TRUNC((count_event2/(nb_samples+1)),3)  avge3, 
           TRUNC((count_event3/(nb_samples+1)),3)  avge4,  
           TRUNC((count_event4/(nb_samples+1)),3)  avge5,  
           TRUNC((count_event5/(nb_samples+1)),3)  avge6,  
           TRUNC((count_event6/(nb_samples+1)),3)  avge7,  
           TRUNC((count_event7/(nb_samples+1)),3)  avge8,  
           TRUNC((count_event8/(nb_samples+1)),3)  avge9,  
           TRUNC((count_event9/(nb_samples+1)),3)  avge10, 
           TRUNC((count_event10/(nb_samples+1)),3) avge11, 
           TRUNC((count_event11/(nb_samples+1)),3) avge12, 
           TRUNC((count_event12/(nb_samples+1)),3) avge13,  
           event_name0,
           event_name1,
           event_name2,
           event_name3,
           event_name4,
           event_name5,
           event_name6,
           event_name7,
           event_name8,
           event_name9,
           event_name10,
           event_name11,
           event_name12
    FROM 
       (SELECT NVL(co_base_qry.sample_yyyymmddhhmi30s,time_window.start_time) sample_yyyymmddhhmi30s,
               NVL(co_base_qry.nb_samples,1)    nb_samples,
               NVL(co_base_qry.count_event0,0)  count_event0,
               NVL(co_base_qry.count_event1,0)  count_event1,
               NVL(co_base_qry.count_event2,0)  count_event2,
               NVL(co_base_qry.count_event3,0)  count_event3,
               NVL(co_base_qry.count_event4,0)  count_event4,
               NVL(co_base_qry.count_event5,0)  count_event5,
               NVL(co_base_qry.count_event6,0)  count_event6,
               NVL(co_base_qry.count_event7,0)  count_event7,
               NVL(co_base_qry.count_event8,0)  count_event8,
               NVL(co_base_qry.count_event9,0)  count_event9,
               NVL(co_base_qry.count_event10,0) count_event10,
               NVL(co_base_qry.count_event11,0) count_event11,
               NVL(co_base_qry.count_event12,0) count_event12,
               co_base_qry.event_name0,
               co_base_qry.event_name1,
               co_base_qry.event_name2,
               co_base_qry.event_name3,
               co_base_qry.event_name4,
               co_base_qry.event_name5,
               co_base_qry.event_name6,
               co_base_qry.event_name7,
               co_base_qry.event_name8,
               co_base_qry.event_name9,
               co_base_qry.event_name10,
               co_base_qry.event_name11,
               co_base_qry.event_name12
        FROM
           (SELECT TO_CHAR(SYSDATE - ((LEVEL*30)/24/60/60),'YYYYMMDDHH24MI') || TO_CHAR(TRUNC(TO_NUMBER(TO_CHAR(SYSDATE - ((LEVEL*30)/24/60/60),'SS'))/30)) start_time
            FROM DUAL 
            CONNECT BY LEVEL <= 122
            ) time_window
        LEFT OUTER JOIN 
           (SELECT TO_CHAR(sample_time,'YYYYMMDDHH24MI') || TO_CHAR(TRUNC(TO_NUMBER(TO_CHAR(sample_time,'SS'))/30)) sample_yyyymmddhhmi30s,
                   MAX(sample_id) - MIN(sample_id) nb_samples,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),-1,1)) count_event0,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),1,1))  count_event1,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),2,1))  count_event2,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),3,1))  count_event3,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),4,1))  count_event4,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),5,1))  count_event5,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),6,1))  count_event6,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),7,1))  count_event7,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),8,1))  count_event8,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),9,1))  count_event9,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),10,1)) count_event10,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),11,1)) count_event11,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),12,1)) count_event12,
                   'cpu'    event_name0,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),1,sess_event.event))  event_name1,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),2,sess_event.event))  event_name2,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),3,sess_event.event))  event_name3,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),4,sess_event.event))  event_name4,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),5,sess_event.event))  event_name5,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),6,sess_event.event))  event_name6,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),7,sess_event.event))  event_name7,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),8,sess_event.event))  event_name8,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),9,sess_event.event))  event_name9,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),10,sess_event.event)) event_name10,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),11,sess_event.event)) event_name11,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),12,sess_event.event)) event_name12
            FROM lss$_sampling_session lss
            LEFT OUTER JOIN session_events sess_event
              ON sess_event.event = lss.event
            WHERE TO_CHAR(lss.sid) || ',' || TO_CHAR(lss.serial#) || ',' || TO_CHAR(lss.con_id) = get_current_session
            GROUP BY TO_CHAR(sample_time,'YYYYMMDDHH24MI') || TO_CHAR(TRUNC(TO_NUMBER(TO_CHAR(sample_time,'SS'))/30))
            ) co_base_qry
          ON time_window.start_time=co_base_qry.sample_yyyymmddhhmi30s
       )
  );

Modified source query

We will use the query defined in the part XXIV as a starting point. We will modify the source query as follow:

        SELECT BEGIN_TIME,
               C_EVENT0,
               C_EVENT1,
               C_EVENT2,
               C_EVENT3,
               C_EVENT4,
               C_EVENT5,
               C_EVENT6,
               C_EVENT7,
               C_EVENT8,
               C_EVENT9,
               C_EVENT10,
               C_EVENT11,
               C_EVENT12,
               SESSION_ID,
               EVENT_NAME0,
               EVENT_NAME1,
               EVENT_NAME2,
               EVENT_NAME3,
               EVENT_NAME4,
               EVENT_NAME5,
               EVENT_NAME6,
               EVENT_NAME7,
               EVENT_NAME8,
               EVENT_NAME9,
               EVENT_NAME10,
               EVENT_NAME11,
               EVENT_NAME12,
               MAX_EVENT
        FROM v$session_activity30s_lss
        ORDER BY sample_yyyymmddhhmi30s

XSLT processing

We will use the query defined in the part XXIV as a starting point with the following modifications:

  • We will only display the EVENT_NAMEyy legends that are meaningful e.g. not NULL. In order to do that we will add “choose” elements,
  • A vertical line and a time label are now displayed every 10 positions.

XSLT variables

We will add twelve additional variables in the XSLT document:

  • <xsl:variable name="event_name0"><xsl:value-of select="/descendant::EVENT_NAME0[position()=1]"/></xsl:variable>

    Event name 0,

  • <xsl:variable name="event_name12"><xsl:value-of select="/descendant::EVENT_NAME12[position()=1]"/></xsl:variable>

    Event name 12.

Furthermore:

  • The variable “bar_width” is set to 5.

Modified query

SET LINESIZE      4000
SET LONGCHUNKSIZE 60000
SET LONG          60000

SET FEEDBACK OFF
SET VERIFY   OFF
SET PAGESIZE 0

SET HEADING OFF

SPOOL generate_svg_25e.svg

SELECT XMLTRANSFORM
   (DBMS_XMLGEN.GETXMLTYPE
      ('SELECT BEGIN_TIME,
               C_EVENT0,
               C_EVENT1,
               C_EVENT2,
               C_EVENT3,
               C_EVENT4,
               C_EVENT5,
               C_EVENT6,
               C_EVENT7,
               C_EVENT8,
               C_EVENT9,
               C_EVENT10,
               C_EVENT11,
               C_EVENT12,
               SESSION_ID,
               EVENT_NAME0,
               EVENT_NAME1,
               EVENT_NAME2,
               EVENT_NAME3,
               EVENT_NAME4,
               EVENT_NAME5,
               EVENT_NAME6,
               EVENT_NAME7,
               EVENT_NAME8,
               EVENT_NAME9,
               EVENT_NAME10,
               EVENT_NAME11,
               EVENT_NAME12,
               MAX_EVENT
        FROM v$session_activity30s_lss
        ORDER BY sample_yyyymmddhhmi30s')
,      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">160</xsl:variable>
     <xsl:variable name="bar_width">5</xsl:variable>
     <xsl:variable name="graph_width"><xsl:value-of select="600+$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">LSS Session Activity : </xsl:variable>
     <xsl:variable name="graph_unit">% Activity</xsl:variable>
     <xsl:variable name="yval_max"><xsl:value-of select="/descendant::MAX_EVENT[position()=1]"/></xsl:variable>
     <xsl:variable name="yval_min">0</xsl:variable>
     <xsl:variable name="var_mult"><xsl:value-of select="100 div (($yval_min)-($yval_max))"/></xsl:variable>
     <xsl:variable name="var_beg"><xsl:value-of select="($graph_height)-($margin_bottom)"/></xsl:variable>
     <xsl:variable name="sid"><xsl:value-of select="/descendant::SESSION_ID[position()=1]"/></xsl:variable>
     <xsl:variable name="event_name0"><xsl:value-of select="/descendant::EVENT_NAME0[position()=1]"/></xsl:variable>
     <xsl:variable name="event_name1"><xsl:value-of select="/descendant::EVENT_NAME1[position()=1]"/></xsl:variable>
     <xsl:variable name="event_name2"><xsl:value-of select="/descendant::EVENT_NAME2[position()=1]"/></xsl:variable>
     <xsl:variable name="event_name3"><xsl:value-of select="/descendant::EVENT_NAME3[position()=1]"/></xsl:variable>
     <xsl:variable name="event_name4"><xsl:value-of select="/descendant::EVENT_NAME4[position()=1]"/></xsl:variable>
     <xsl:variable name="event_name5"><xsl:value-of select="/descendant::EVENT_NAME5[position()=1]"/></xsl:variable>
     <xsl:variable name="event_name6"><xsl:value-of select="/descendant::EVENT_NAME6[position()=1]"/></xsl:variable>
     <xsl:variable name="event_name7"><xsl:value-of select="/descendant::EVENT_NAME7[position()=1]"/></xsl:variable>
     <xsl:variable name="event_name8"><xsl:value-of select="/descendant::EVENT_NAME8[position()=1]"/></xsl:variable>
     <xsl:variable name="event_name9"><xsl:value-of select="/descendant::EVENT_NAME9[position()=1]"/></xsl:variable>
     <xsl:variable name="event_name10"><xsl:value-of select="/descendant::EVENT_NAME10[position()=1]"/></xsl:variable>
     <xsl:variable name="event_name11"><xsl:value-of select="/descendant::EVENT_NAME11[position()=1]"/></xsl:variable>
     <xsl:variable name="event_name12"><xsl:value-of select="/descendant::EVENT_NAME12[position()=1]"/></xsl:variable>
       <xsl:template match="/">'
           )
    || 
    TO_CLOB(
         '<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="concat($graph_name,$sid)"/></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="{($var_beg)-0}"   x2="{($graph_width)-($margin_right)+5}" y2="{($var_beg)-0}"  style="stroke:lightblue;stroke-width:1" />
           <line x1="{($margin_left)-5}" y1="{($var_beg)-25}"  x2="{($graph_width)-($margin_right)+5}" y2="{($var_beg)-25}" style="stroke:lightblue;stroke-width:1" />
           <line x1="{($margin_left)-5}" y1="{($var_beg)-50}"  x2="{($graph_width)-($margin_right)+5}" y2="{($var_beg)-50}" style="stroke:lightblue;stroke-width:1" />
           <line x1="{($margin_left)-5}" y1="{($var_beg)-75}"  x2="{($graph_width)-($margin_right)+5}" y2="{($var_beg)-75}" style="stroke:lightblue;stroke-width:1" />
           <line x1="{($margin_left)-5}" y1="{($var_beg)-100}" x2="{($graph_width)-($margin_right)+5}" y2="{($var_beg)-100}" style="stroke:lightblue;stroke-width:1" />
           <text x="{($margin_left)-24}" y="{($var_beg)-2}"   style="fill: #000000; stroke: none;font-size:8px;text-anchor=start">0</text>
           <text x="{($margin_left)-24}" y="{($var_beg)-25}"  style="fill: #000000; stroke: none;font-size:8px;text-anchor=start">25</text>
           <text x="{($margin_left)-24}" y="{($var_beg)-50}"  style="fill: #000000; stroke: none;font-size:8px;text-anchor=start">50</text>
           <text x="{($margin_left)-24}" y="{($var_beg)-75}"  style="fill: #000000; stroke: none;font-size:8px;text-anchor=start">75</text>
           <text x="{($margin_left)-24}" y="{($var_beg)-100}" style="fill: #000000; stroke: none;font-size:8px;text-anchor=start">100</text>
           <line x1="{$margin_left}" y1="{($var_beg)}" x2="{$margin_left}" y2="{($var_beg)-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 10=0">
                 <text x="{($margin_left)-9+($bar_width*(position()-1))}" y="{($var_beg)+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="{($var_beg)+4}" x2="{($margin_left)+($bar_width*(position()-1))}" y2="{($var_beg)-100}" style="stroke:lightblue;stroke-width:1" /> 
               </xsl:when>
               <xsl:otherwise>
                 <line x1="{($margin_left)+($bar_width*(position()-1))}" y1="{($var_beg)+3}" x2="{($margin_left)+($bar_width*(position()-1))}" y2="{($var_beg)+0}" style="stroke:lightblue;stroke-width:1" /> 
               </xsl:otherwise>
             </xsl:choose>    
           </xsl:for-each>
           <xsl:variable name="v_path0">
             <xsl:for-each select="ROWSET/ROW/C_EVENT0">
               <xsl:variable name="x_val0">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val0">
                 <xsl:value-of select="round(($var_beg)-((($yval_min)-(self::node()))*($var_mult)))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val0,'','',$y_val0,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path0} {$x_val0},{($var_beg)} {$margin_left},{($var_beg)}" style="fill:limegreen;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path1">
             <xsl:for-each select="ROWSET/ROW/C_EVENT1">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val1">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val1">
                 <xsl:value-of select="round(($var_beg)-((($yval_min)-(self::node()))*($var_mult)))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val1,'','',$y_val1,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path0}{$v_path1}" style="fill:hotpink;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path2">
             <xsl:for-each select="ROWSET/ROW/C_EVENT2">
               <xsl:variable name="x_val2">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val2">
                 <xsl:value-of select="round(($var_beg)-((($yval_min)-(self::node()))*($var_mult)))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val2,'','',$y_val2,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path1}{$v_path2}" style="fill:indianred;stroke:none;stroke-width:1" />'
           )
   ||
   TO_CLOB(
          '<xsl:variable name="v_path3">
             <xsl:for-each select="ROWSET/ROW/C_EVENT3">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val3">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val3">
                 <xsl:value-of select="round(($var_beg)-((($yval_min)-(self::node()))*($var_mult)))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val3,'','',$y_val3,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path2}{$v_path3}" style="fill:olive;stroke:none;stroke-width:1" />'
           )
   ||
   TO_CLOB(
          '<xsl:variable name="v_path4">
             <xsl:for-each select="ROWSET/ROW/C_EVENT4">
               <xsl:variable name="x_val4">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val4">
                 <xsl:value-of select="round(($var_beg)-((($yval_min)-(self::node()))*($var_mult)))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val4,'','',$y_val4,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path3}{$v_path4}" style="fill:gray;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path5">
             <xsl:for-each select="ROWSET/ROW/C_EVENT5">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val5">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val5">
                 <xsl:value-of select="round(($var_beg)-((($yval_min)-(self::node()))*($var_mult)))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val5,'','',$y_val5,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path4}{$v_path5}" style="fill:sienna;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path6">
             <xsl:for-each select="ROWSET/ROW/C_EVENT6">
               <xsl:variable name="x_val6">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val6">
                 <xsl:value-of select="round(($var_beg)-((($yval_min)-(self::node()))*($var_mult)))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val6,'','',$y_val6,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path5}{$v_path6}" style="fill:orange;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path7">
             <xsl:for-each select="ROWSET/ROW/C_EVENT7">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val7">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val7">
                 <xsl:value-of select="round(($var_beg)-((($yval_min)-(self::node()))*($var_mult)))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val7,'','',$y_val7,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path6}{$v_path7}" style="fill:tan;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path8">
             <xsl:for-each select="ROWSET/ROW/C_EVENT8">
               <xsl:variable name="x_val8">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val8">
                 <xsl:value-of select="round(($var_beg)-((($yval_min)-(self::node()))*($var_mult)))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val8,'','',$y_val8,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path7}{$v_path8}" style="fill:royalblue;stroke:none;stroke-width:1" />'
           )
   ||
   TO_CLOB(
          '<xsl:variable name="v_path9">
             <xsl:for-each select="ROWSET/ROW/C_EVENT9">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val9">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val9">
                 <xsl:value-of select="round(($var_beg)-((($yval_min)-(self::node()))*($var_mult)))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val9,'','',$y_val9,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path8}{$v_path9}" style="fill:skyblue;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path10">
             <xsl:for-each select="ROWSET/ROW/C_EVENT10">
               <xsl:variable name="x_val10">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val10">
                 <xsl:value-of select="round(($var_beg)-((($yval_min)-(self::node()))*($var_mult)))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val10,'','',$y_val10,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path9}{$v_path10}" style="fill:lightcyan;stroke:none;stroke-width:1" />'
           )
   ||
   TO_CLOB(
          '<xsl:variable name="v_path11">
             <xsl:for-each select="ROWSET/ROW/C_EVENT11">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val11">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val11">
                 <xsl:value-of select="round(($var_beg)-((($yval_min)-(self::node()))*($var_mult)))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val11,'','',$y_val11,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path10}{$v_path11}" style="fill:lightgray;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path12">
             <xsl:for-each select="ROWSET/ROW/C_EVENT12">
               <xsl:variable name="x_val12">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val12">
                 <xsl:value-of select="round(($var_beg)-((($yval_min)-(self::node()))*($var_mult)))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val12,'','',$y_val12,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path11}{$v_path12}" style="fill:bisque;stroke:none;stroke-width:1" />'
           )
   ||
   TO_CLOB(
          '<xsl:choose>
             <xsl:when test="string-length($event_name0)&gt;0">
               <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+5}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="$event_name0"/></text>
               <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+0}" width="{10}" height="{6}" fill="limegreen" stroke="black"/> 
             </xsl:when>
           </xsl:choose> 
           <xsl:choose>
             <xsl:when test="string-length($event_name1)&gt;0">
               <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+13}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="$event_name1"/></text>
               <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+8}" width="{10}" height="{6}" fill="hotpink" stroke="black"/> 
             </xsl:when>
           </xsl:choose> 
           <xsl:choose>
             <xsl:when test="string-length($event_name2)&gt;0">
               <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+21}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="$event_name2"/></text>
               <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+16}" width="{10}" height="{6}" fill="indianred" stroke="black"/> 
             </xsl:when>
           </xsl:choose> 
           <xsl:choose>
             <xsl:when test="string-length($event_name3)&gt;0">  
               <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+29}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="$event_name3"/></text>
               <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+24}" width="{10}" height="{6}" fill="olive" stroke="black"/> 
             </xsl:when>
           </xsl:choose>  
           <xsl:choose>
             <xsl:when test="string-length($event_name4)&gt;0"> 
               <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+37}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="$event_name4"/></text>
               <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+32}" width="{10}" height="{6}" fill="gray" stroke="black"/> 
             </xsl:when>
           </xsl:choose> 
           <xsl:choose>
             <xsl:when test="string-length($event_name5)&gt;0">
               <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+45}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="$event_name5"/></text>
               <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+40}" width="{10}" height="{6}" fill="sienna" stroke="black"/>
             </xsl:when>
           </xsl:choose>'
           ) 
    || 
    TO_CLOB(
          '<xsl:choose>
             <xsl:when test="string-length($event_name6)&gt;0">
               <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+53}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="$event_name6"/></text>
               <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+48}" width="{10}" height="{6}" fill="orange" stroke="black"/> 
             </xsl:when>
           </xsl:choose> 
           <xsl:choose>
             <xsl:when test="string-length($event_name7)&gt;0">
               <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+61}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="$event_name7"/></text>
               <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+56}" width="{10}" height="{6}" fill="tan" stroke="black"/>  
             </xsl:when>
           </xsl:choose>
           <xsl:choose>
             <xsl:when test="string-length($event_name8)&gt;0">
               <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+69}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="$event_name8"/></text>
               <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+64}" width="{10}" height="{6}" fill="royalblue" stroke="black"/> 
             </xsl:when>
           </xsl:choose> 
           <xsl:choose>
             <xsl:when test="string-length($event_name9)&gt;0">
               <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+77}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="$event_name9"/></text>
               <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+72}" width="{10}" height="{6}" fill="skyblue" stroke="black"/>
             </xsl:when>
           </xsl:choose> 
           <xsl:choose>
             <xsl:when test="string-length($event_name10)&gt;0">
               <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+85}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="$event_name10"/></text>
               <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+80}" width="{10}" height="{6}" fill="lightcyan" stroke="black"/> 
             </xsl:when>
           </xsl:choose> 
           <xsl:choose>
             <xsl:when test="string-length($event_name11)&gt;0">
               <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+93}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="$event_name11"/></text>
               <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+88}" width="{10}" height="{6}" fill="lightgray" stroke="black"/> 
             </xsl:when>
           </xsl:choose>  
           <xsl:choose>
             <xsl:when test="string-length($event_name12)&gt;0">
               <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+101}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="$event_name12"/></text>
               <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+96}" width="{10}" height="{6}" fill="bisque" stroke="black"/>
             </xsl:when>
           </xsl:choose>   
         </svg>
       </xsl:template>
     </xsl:stylesheet>'
           )
   )
   ) 
FROM dual;

SPOOL OFF
SET HEADING ON

SET VERIFY   ON
SET FEEDBACK ON

Result:

generate_svg_25e

Remarks:

  • The query has been executed from the CDB$ROOT container by the C##LSS common user,
  • The view v$session_activity30s_lss has been created from the CDB$ROOT container in the C##LSS schema,
  • The system variables LINESIZE and LONGCHUNKSIZE have been increased to 4000 and 60000 respectively,
  • The LSS sampling period interval is set to 2 seconds.

Generating SVG graphics with SQL*Plus – Part XXIV – Stacked area graph – Session Activity – Light Sampling Sessions

Scope

In the previous post we have displayed the top 20 activity sessions. It could be interesting to know how much a session is waiting on such or such event or is using the cpu. We will change the sampling period interval to 2 seconds.
We will create a view in order to display the session activity and we will use a function to get the session id.

Function get_current_session

This function will return the session id that we want to analyse. Basically you could store the session id in a table and retrieve it with this function. You will find a example below:

CREATE OR REPLACE FUNCTION get_current_session RETURN NUMBER 
AS 
   v_param_value lss$parameter.parameter_value%TYPE;
BEGIN

   SELECT parameter_value
   INTO v_param_value
   FROM LSS$parameter
   WHERE parameter_name = 'current_session';
   
   RETURN TO_NUMBER(v_param_value);
   
   EXCEPTION
      WHEN TOO_MANY_ROWS THEN
         RETURN -1;
      WHEN NO_DATA_FOUND THEN
         RETURN -1;
      WHEN OTHERS THEN
         RAISE;
         
END get_current_session;

View creation – Step 1

The starting point of this view will be v$aas_light_sampling_sessions.
The query name session_events gives the top 12 event activities linked to the wait events of a session (excluded the cpu activity) as follow:

WITH session_events AS
   (
   SELECT event,
          COUNT(*) count_event, 
          RANK() OVER (ORDER BY COUNT(*) DESC, EVENT) rank_event 
   FROM lss$_sampling_session
   WHERE SID = get_current_session
     AND sample_time >= SYSDATE -(1/24) 
     AND session_state <> 'C'
   GROUP BY event
   ORDER BY count_event DESC
   FETCH FIRST 12 ROWS ONLY
   )

View creation – Step 2

Every minute we will count the number of events that are linked to a wait class or a cpu event for the target session as follow:

            SELECT TO_CHAR(sample_time,'YYYYMMDDHH24MI') sample_yyyymmddhhmi,
                   MAX(sample_id) - MIN(sample_id) nb_samples,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),-1,1)) count_event0,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),1,1))  count_event1,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),2,1))  count_event2,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),3,1))  count_event3,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),4,1))  count_event4,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),5,1))  count_event5,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),6,1))  count_event6,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),7,1))  count_event7,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),8,1))  count_event8,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),9,1))  count_event9,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),10,1)) count_event10,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),11,1)) count_event11,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),12,1)) count_event12,
                   'cpu'    event_name0,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),1,sess_event.event))  event_name1,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),2,sess_event.event))  event_name2,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),3,sess_event.event))  event_name3,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),4,sess_event.event))  event_name4,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),5,sess_event.event))  event_name5,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),6,sess_event.event))  event_name6,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),7,sess_event.event))  event_name7,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),8,sess_event.event))  event_name8,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),9,sess_event.event))  event_name9,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),10,sess_event.event)) event_name10,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),11,sess_event.event)) event_name11,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),12,sess_event.event)) event_name12
            FROM lss$_sampling_session lss
            LEFT OUTER JOIN session_events sess_event
              ON sess_event.event = lss.event
            WHERE lss.sid = get_current_session
            GROUP BY TO_CHAR(sample_time,'YYYYMMDDHH24MI')

We will also store the different event names.

View creation – Step 3

In the LSS sampling process, it might happen that a specific period of time does not contain any data e.g. LSS process is not working during this period. We will handle this sampling process inactivity during the last hour as follow:

        SELECT NVL(co_base_qry.sample_yyyymmddhhmi,time_window.start_time) sample_yyyymmddhhmi,
               NVL(co_base_qry.nb_samples,1)    nb_samples,
               NVL(co_base_qry.count_event0,0)  count_event0,
               NVL(co_base_qry.count_event1,0)  count_event1,
               NVL(co_base_qry.count_event2,0)  count_event2,
               NVL(co_base_qry.count_event3,0)  count_event3,
               NVL(co_base_qry.count_event4,0)  count_event4,
               NVL(co_base_qry.count_event5,0)  count_event5,
               NVL(co_base_qry.count_event6,0)  count_event6,
               NVL(co_base_qry.count_event7,0)  count_event7,
               NVL(co_base_qry.count_event8,0)  count_event8,
               NVL(co_base_qry.count_event9,0)  count_event9,
               NVL(co_base_qry.count_event10,0) count_event10,
               NVL(co_base_qry.count_event11,0) count_event11,
               NVL(co_base_qry.count_event12,0) count_event12,
               co_base_qry.event_name0,
               co_base_qry.event_name1,
               co_base_qry.event_name2,
               co_base_qry.event_name3,
               co_base_qry.event_name4,
               co_base_qry.event_name5,
               co_base_qry.event_name6,
               co_base_qry.event_name7,
               co_base_qry.event_name8,
               co_base_qry.event_name9,
               co_base_qry.event_name10,
               co_base_qry.event_name11,
               co_base_qry.event_name12
        FROM
           (SELECT TO_CHAR(SYSDATE - (LEVEL/24/60),'YYYYMMDDHH24MI') start_time
            FROM DUAL 
            CONNECT BY LEVEL <= 61
            ) time_window
        LEFT OUTER JOIN 
           (SELECT TO_CHAR(sample_time,'YYYYMMDDHH24MI') sample_yyyymmddhhmi,
                   MAX(sample_id) - MIN(sample_id) nb_samples,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),-1,1)) count_event0,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),1,1))  count_event1,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),2,1))  count_event2,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),3,1))  count_event3,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),4,1))  count_event4,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),5,1))  count_event5,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),6,1))  count_event6,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),7,1))  count_event7,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),8,1))  count_event8,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),9,1))  count_event9,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),10,1)) count_event10,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),11,1)) count_event11,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),12,1)) count_event12,
                   'cpu'    event_name0,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),1,sess_event.event))  event_name1,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),2,sess_event.event))  event_name2,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),3,sess_event.event))  event_name3,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),4,sess_event.event))  event_name4,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),5,sess_event.event))  event_name5,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),6,sess_event.event))  event_name6,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),7,sess_event.event))  event_name7,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),8,sess_event.event))  event_name8,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),9,sess_event.event))  event_name9,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),10,sess_event.event)) event_name10,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),11,sess_event.event)) event_name11,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),12,sess_event.event)) event_name12
            FROM lss$_sampling_session lss
            LEFT OUTER JOIN session_events sess_event
              ON sess_event.event = lss.event
            WHERE lss.sid = get_current_session
            GROUP BY TO_CHAR(sample_time,'YYYYMMDDHH24MI')
            ) co_base_qry
          ON time_window.start_time=co_base_qry.sample_yyyymmddhhmi

View creation – Step 4

To define how many events in average that are linked to the target session, we will count the top 12 wait events plus the cpu event on a period of time of one minute and we will divide by the number of samples plus one as follow:

    SELECT sample_yyyymmddhhmi,
           TRUNC((count_event0/(nb_samples+1)),3)  avge1,  
           TRUNC((count_event1/(nb_samples+1)),3)  avge2,  
           TRUNC((count_event2/(nb_samples+1)),3)  avge3, 
           TRUNC((count_event3/(nb_samples+1)),3)  avge4,  
           TRUNC((count_event4/(nb_samples+1)),3)  avge5,  
           TRUNC((count_event5/(nb_samples+1)),3)  avge6,  
           TRUNC((count_event6/(nb_samples+1)),3)  avge7,  
           TRUNC((count_event7/(nb_samples+1)),3)  avge8,  
           TRUNC((count_event8/(nb_samples+1)),3)  avge9,  
           TRUNC((count_event9/(nb_samples+1)),3)  avge10, 
           TRUNC((count_event10/(nb_samples+1)),3) avge11, 
           TRUNC((count_event11/(nb_samples+1)),3) avge12, 
           TRUNC((count_event12/(nb_samples+1)),3) avge13,  
           event_name0,
           event_name1,
           event_name2,
           event_name3,
           event_name4,
           event_name5,
           event_name6,
           event_name7,
           event_name8,
           event_name9,
           event_name10,
           event_name11,
           event_name12
    FROM 
       (SELECT NVL(co_base_qry.sample_yyyymmddhhmi,time_window.start_time) sample_yyyymmddhhmi,
               NVL(co_base_qry.nb_samples,1)    nb_samples,
               NVL(co_base_qry.count_event0,0)  count_event0,
               NVL(co_base_qry.count_event1,0)  count_event1,
               NVL(co_base_qry.count_event2,0)  count_event2,
               NVL(co_base_qry.count_event3,0)  count_event3,
               NVL(co_base_qry.count_event4,0)  count_event4,
               NVL(co_base_qry.count_event5,0)  count_event5,
               NVL(co_base_qry.count_event6,0)  count_event6,
               NVL(co_base_qry.count_event7,0)  count_event7,
               NVL(co_base_qry.count_event8,0)  count_event8,
               NVL(co_base_qry.count_event9,0)  count_event9,
               NVL(co_base_qry.count_event10,0) count_event10,
               NVL(co_base_qry.count_event11,0) count_event11,
               NVL(co_base_qry.count_event12,0) count_event12,
               co_base_qry.event_name0,
               co_base_qry.event_name1,
               co_base_qry.event_name2,
               co_base_qry.event_name3,
               co_base_qry.event_name4,
               co_base_qry.event_name5,
               co_base_qry.event_name6,
               co_base_qry.event_name7,
               co_base_qry.event_name8,
               co_base_qry.event_name9,
               co_base_qry.event_name10,
               co_base_qry.event_name11,
               co_base_qry.event_name12
        FROM
           (SELECT TO_CHAR(SYSDATE - (LEVEL/24/60),'YYYYMMDDHH24MI') start_time
            FROM DUAL 
            CONNECT BY LEVEL <= 61
            ) time_window
        LEFT OUTER JOIN 
           (SELECT TO_CHAR(sample_time,'YYYYMMDDHH24MI') sample_yyyymmddhhmi,
                   MAX(sample_id) - MIN(sample_id) nb_samples,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),-1,1)) count_event0,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),1,1))  count_event1,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),2,1))  count_event2,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),3,1))  count_event3,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),4,1))  count_event4,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),5,1))  count_event5,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),6,1))  count_event6,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),7,1))  count_event7,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),8,1))  count_event8,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),9,1))  count_event9,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),10,1)) count_event10,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),11,1)) count_event11,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),12,1)) count_event12,
                   'cpu'    event_name0,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),1,sess_event.event))  event_name1,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),2,sess_event.event))  event_name2,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),3,sess_event.event))  event_name3,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),4,sess_event.event))  event_name4,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),5,sess_event.event))  event_name5,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),6,sess_event.event))  event_name6,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),7,sess_event.event))  event_name7,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),8,sess_event.event))  event_name8,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),9,sess_event.event))  event_name9,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),10,sess_event.event)) event_name10,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),11,sess_event.event)) event_name11,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),12,sess_event.event)) event_name12
            FROM lss$_sampling_session lss
            LEFT OUTER JOIN session_events sess_event
              ON sess_event.event = lss.event
            WHERE lss.sid = get_current_session
            GROUP BY TO_CHAR(sample_time,'YYYYMMDDHH24MI')
            ) co_base_qry
          ON time_window.start_time=co_base_qry.sample_yyyymmddhhmi
       )

View creation – Step 5

Finally we will accumulate the different events AVGE from the EVENT0 to EVENT12 event as follow:

CREATE OR REPLACE VIEW v$session_activity_lss
AS
WITH session_events AS
   (
   SELECT event,
          COUNT(*) count_event, 
          RANK() OVER (ORDER BY COUNT(*) DESC, EVENT) rank_event 
   FROM lss$_sampling_session
   WHERE SID = get_current_session
     AND sample_time >= SYSDATE -(1/24) 
     AND session_state <> 'C'
   GROUP BY event
   ORDER BY count_event DESC
   FETCH FIRST 12 ROWS ONLY
   )
SELECT sample_yyyymmddhhmi,
       SUBSTR(sample_yyyymmddhhmi,9,2) || ':' || SUBSTR(sample_yyyymmddhhmi,11,2) BEGIN_TIME,
       avge1                                                                             C_EVENT0,
       avge1+avge2                                                                       C_EVENT1,
       avge1+avge2+avge3                                                                 C_EVENT2,
       avge1+avge2+avge3+avge4                                                           C_EVENT3,
       avge1+avge2+avge3+avge4+avge5                                                     C_EVENT4,
       avge1+avge2+avge3+avge4+avge5+avge6                                               C_EVENT5,
       avge1+avge2+avge3+avge4+avge5+avge6+avge7                                         C_EVENT6,
       avge1+avge2+avge3+avge4+avge5+avge6+avge7+avge8                                   C_EVENT7,
       avge1+avge2+avge3+avge4+avge5+avge6+avge7+avge8+avge9                             C_EVENT8,
       avge1+avge2+avge3+avge4+avge5+avge6+avge7+avge8+avge9+avge10                      C_EVENT9,
       avge1+avge2+avge3+avge4+avge5+avge6+avge7+avge8+avge9+avge10+avge11               C_EVENT10,
       avge1+avge2+avge3+avge4+avge5+avge6+avge7+avge8+avge9+avge10+avge11+avge12        C_EVENT11,
       avge1+avge2+avge3+avge4+avge5+avge6+avge7+avge8+avge9+avge10+avge11+avge12+avge13 C_EVENT12,
       MAX(CEIL(avge1+avge2+avge3+avge4+avge5+avge6+avge7+avge8+avge9+avge10+avge11+avge12+avge13)) OVER() MAX_EVENT,
       (SELECT get_current_session FROM DUAL) session_id,
       MAX(event_name0)  OVER() EVENT_NAME0,
       MAX(event_name1)  OVER() EVENT_NAME1,
       MAX(event_name2)  OVER() EVENT_NAME2,
       MAX(event_name3)  OVER() EVENT_NAME3,
       MAX(event_name4)  OVER() EVENT_NAME4,
       MAX(event_name5)  OVER() EVENT_NAME5,
       MAX(event_name6)  OVER() EVENT_NAME6,
       MAX(event_name7)  OVER() EVENT_NAME7,
       MAX(event_name8)  OVER() EVENT_NAME8,
       MAX(event_name9)  OVER() EVENT_NAME9,
       MAX(event_name10) OVER() EVENT_NAME10,
       MAX(event_name11) OVER() EVENT_NAME11,
       MAX(event_name12) OVER() EVENT_NAME12
FROM
   (SELECT sample_yyyymmddhhmi,
           TRUNC((count_event0/(nb_samples+1)),3)  avge1,  
           TRUNC((count_event1/(nb_samples+1)),3)  avge2,  
           TRUNC((count_event2/(nb_samples+1)),3)  avge3, 
           TRUNC((count_event3/(nb_samples+1)),3)  avge4,  
           TRUNC((count_event4/(nb_samples+1)),3)  avge5,  
           TRUNC((count_event5/(nb_samples+1)),3)  avge6,  
           TRUNC((count_event6/(nb_samples+1)),3)  avge7,  
           TRUNC((count_event7/(nb_samples+1)),3)  avge8,  
           TRUNC((count_event8/(nb_samples+1)),3)  avge9,  
           TRUNC((count_event9/(nb_samples+1)),3)  avge10, 
           TRUNC((count_event10/(nb_samples+1)),3) avge11, 
           TRUNC((count_event11/(nb_samples+1)),3) avge12, 
           TRUNC((count_event12/(nb_samples+1)),3) avge13,  
           event_name0,
           event_name1,
           event_name2,
           event_name3,
           event_name4,
           event_name5,
           event_name6,
           event_name7,
           event_name8,
           event_name9,
           event_name10,
           event_name11,
           event_name12
    FROM 
       (SELECT NVL(co_base_qry.sample_yyyymmddhhmi,time_window.start_time) sample_yyyymmddhhmi,
               NVL(co_base_qry.nb_samples,1)    nb_samples,
               NVL(co_base_qry.count_event0,0)  count_event0,
               NVL(co_base_qry.count_event1,0)  count_event1,
               NVL(co_base_qry.count_event2,0)  count_event2,
               NVL(co_base_qry.count_event3,0)  count_event3,
               NVL(co_base_qry.count_event4,0)  count_event4,
               NVL(co_base_qry.count_event5,0)  count_event5,
               NVL(co_base_qry.count_event6,0)  count_event6,
               NVL(co_base_qry.count_event7,0)  count_event7,
               NVL(co_base_qry.count_event8,0)  count_event8,
               NVL(co_base_qry.count_event9,0)  count_event9,
               NVL(co_base_qry.count_event10,0) count_event10,
               NVL(co_base_qry.count_event11,0) count_event11,
               NVL(co_base_qry.count_event12,0) count_event12,
               co_base_qry.event_name0,
               co_base_qry.event_name1,
               co_base_qry.event_name2,
               co_base_qry.event_name3,
               co_base_qry.event_name4,
               co_base_qry.event_name5,
               co_base_qry.event_name6,
               co_base_qry.event_name7,
               co_base_qry.event_name8,
               co_base_qry.event_name9,
               co_base_qry.event_name10,
               co_base_qry.event_name11,
               co_base_qry.event_name12
        FROM
           (SELECT TO_CHAR(SYSDATE - (LEVEL/24/60),'YYYYMMDDHH24MI') start_time
            FROM DUAL 
            CONNECT BY LEVEL <= 61
            ) time_window
        LEFT OUTER JOIN 
           (SELECT TO_CHAR(sample_time,'YYYYMMDDHH24MI') sample_yyyymmddhhmi,
                   MAX(sample_id) - MIN(sample_id) nb_samples,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),-1,1)) count_event0,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),1,1))  count_event1,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),2,1))  count_event2,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),3,1))  count_event3,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),4,1))  count_event4,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),5,1))  count_event5,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),6,1))  count_event6,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),7,1))  count_event7,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),8,1))  count_event8,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),9,1))  count_event9,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),10,1)) count_event10,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),11,1)) count_event11,
                   COUNT(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),12,1)) count_event12,
                   'cpu'    event_name0,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),1,sess_event.event))  event_name1,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),2,sess_event.event))  event_name2,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),3,sess_event.event))  event_name3,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),4,sess_event.event))  event_name4,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),5,sess_event.event))  event_name5,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),6,sess_event.event))  event_name6,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),7,sess_event.event))  event_name7,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),8,sess_event.event))  event_name8,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),9,sess_event.event))  event_name9,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),10,sess_event.event)) event_name10,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),11,sess_event.event)) event_name11,
                   MAX(DECODE(DECODE(session_state,'C',-1,sess_event.rank_event),12,sess_event.event)) event_name12
            FROM lss$_sampling_session lss
            LEFT OUTER JOIN session_events sess_event
              ON sess_event.event = lss.event
            WHERE lss.sid = get_current_session
            GROUP BY TO_CHAR(sample_time,'YYYYMMDDHH24MI')
            ) co_base_qry
          ON time_window.start_time=co_base_qry.sample_yyyymmddhhmi
       )
  );

Modified source query

We will modify the source query as follow:

        SELECT BEGIN_TIME,
               C_EVENT0,
               C_EVENT1,
               C_EVENT2,
               C_EVENT3,
               C_EVENT4,
               C_EVENT5,
               C_EVENT6,
               C_EVENT7,
               C_EVENT8,
               C_EVENT9,
               C_EVENT10,
               C_EVENT11,
               C_EVENT12,
               SESSION_ID,
               EVENT_NAME0,
               EVENT_NAME1,
               EVENT_NAME2,
               EVENT_NAME3,
               EVENT_NAME4,
               EVENT_NAME5,
               EVENT_NAME6,
               EVENT_NAME7,
               EVENT_NAME8,
               EVENT_NAME9,
               EVENT_NAME10,
               EVENT_NAME11,
               EVENT_NAME12,
               MAX_EVENT
        FROM v$session_activity_lss
        ORDER BY sample_yyyymmddhhmi

XSLT processing

We will use the query defined in the part XXI as a starting point with the following modifications:

  • The differents “for-each” “ROWSET/ROW/C_CPU” to “ROWSET/ROW/C_CLUSTER” have been replaced by “ROWSET/ROW/C_EVENT0” to “ROWSET/ROW/C_EVENT12”,
  • Utilization of two variables “var_mult” and “var_beg” to simplify formulas.

XSLT variables

We will add three additional variables in the XSLT document:

  • <xsl:variable name="var_mult"><xsl:value-of select="100 div (($yval_min)-($yval_max))"/></xsl:variable>

    Variable used to simplify several formulas,

  • <xsl:variable name="var_beg"><xsl:value-of select="($graph_height)-($margin_bottom)"/></xsl:variable>

    Variable also used to simplify several formulas,

  • <xsl:variable name="sid"><xsl:value-of select="/descendant::SESSION_ID[position()=1]"/></xsl:variable>

    Target session id.

Furthermore:

  • The variable “margin_rigth” is set to 160,
  • The variable “graph_name” is set to ‘LSS Session Activity : ‘,
  • The variable “yval_max” is set to the first value of the column MAX_EVENT.

Modified query

SET LINESIZE      2000
SET LONGCHUNKSIZE 30000
SET LONG          30000

SET FEEDBACK OFF
SET VERIFY   OFF
SET PAGESIZE 0

SET HEADING OFF

SPOOL generate_svg_24d.svg

SELECT XMLTRANSFORM
   (DBMS_XMLGEN.GETXMLTYPE
      ('SELECT BEGIN_TIME,
               C_EVENT0,
               C_EVENT1,
               C_EVENT2,
               C_EVENT3,
               C_EVENT4,
               C_EVENT5,
               C_EVENT6,
               C_EVENT7,
               C_EVENT8,
               C_EVENT9,
               C_EVENT10,
               C_EVENT11,
               C_EVENT12,
               SESSION_ID,
               EVENT_NAME0,
               EVENT_NAME1,
               EVENT_NAME2,
               EVENT_NAME3,
               EVENT_NAME4,
               EVENT_NAME5,
               EVENT_NAME6,
               EVENT_NAME7,
               EVENT_NAME8,
               EVENT_NAME9,
               EVENT_NAME10,
               EVENT_NAME11,
               EVENT_NAME12,
               MAX_EVENT
        FROM v$session_activity_lss
        ORDER BY sample_yyyymmddhhmi')
,      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">160</xsl:variable>
     <xsl:variable name="bar_width">10</xsl:variable>
     <xsl:variable name="graph_width"><xsl:value-of select="600+$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">LSS Session Activity : </xsl:variable>
     <xsl:variable name="graph_unit">% Activity</xsl:variable>
     <xsl:variable name="yval_max"><xsl:value-of select="/descendant::MAX_EVENT[position()=1]"/></xsl:variable>
     <xsl:variable name="yval_min">0</xsl:variable>
     <xsl:variable name="var_mult"><xsl:value-of select="100 div (($yval_min)-($yval_max))"/></xsl:variable>
     <xsl:variable name="var_beg"><xsl:value-of select="($graph_height)-($margin_bottom)"/></xsl:variable>
     <xsl:variable name="sid"><xsl:value-of select="/descendant::SESSION_ID[position()=1]"/></xsl:variable>
       <xsl:template match="/">'
           )
    || 
    TO_CLOB(
         '<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="concat($graph_name,$sid)"/></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="{($var_beg)-0}"   x2="{($graph_width)-($margin_right)+5}" y2="{($var_beg)-0}"  style="stroke:lightblue;stroke-width:1" />
           <line x1="{($margin_left)-5}" y1="{($var_beg)-25}"  x2="{($graph_width)-($margin_right)+5}" y2="{($var_beg)-25}" style="stroke:lightblue;stroke-width:1" />
           <line x1="{($margin_left)-5}" y1="{($var_beg)-50}"  x2="{($graph_width)-($margin_right)+5}" y2="{($var_beg)-50}" style="stroke:lightblue;stroke-width:1" />
           <line x1="{($margin_left)-5}" y1="{($var_beg)-75}"  x2="{($graph_width)-($margin_right)+5}" y2="{($var_beg)-75}" style="stroke:lightblue;stroke-width:1" />
           <line x1="{($margin_left)-5}" y1="{($var_beg)-100}" x2="{($graph_width)-($margin_right)+5}" y2="{($var_beg)-100}" style="stroke:lightblue;stroke-width:1" />
           <text x="{($margin_left)-24}" y="{($var_beg)-2}"   style="fill: #000000; stroke: none;font-size:8px;text-anchor=start">0</text>
           <text x="{($margin_left)-24}" y="{($var_beg)-25}"  style="fill: #000000; stroke: none;font-size:8px;text-anchor=start">25</text>
           <text x="{($margin_left)-24}" y="{($var_beg)-50}"  style="fill: #000000; stroke: none;font-size:8px;text-anchor=start">50</text>
           <text x="{($margin_left)-24}" y="{($var_beg)-75}"  style="fill: #000000; stroke: none;font-size:8px;text-anchor=start">75</text>
           <text x="{($margin_left)-24}" y="{($var_beg)-100}" style="fill: #000000; stroke: none;font-size:8px;text-anchor=start">100</text>
           <line x1="{$margin_left}" y1="{($var_beg)}" x2="{$margin_left}" y2="{($var_beg)-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="{($var_beg)+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="{($var_beg)+4}" x2="{($margin_left)+($bar_width*(position()-1))}" y2="{($var_beg)-100}" style="stroke:lightblue;stroke-width:1" /> 
               </xsl:when>
               <xsl:otherwise>
                 <line x1="{($margin_left)+($bar_width*(position()-1))}" y1="{($var_beg)+3}" x2="{($margin_left)+($bar_width*(position()-1))}" y2="{($var_beg)+0}" style="stroke:lightblue;stroke-width:1" /> 
               </xsl:otherwise>
             </xsl:choose>    
           </xsl:for-each>
           <xsl:variable name="v_path0">
             <xsl:for-each select="ROWSET/ROW/C_EVENT0">
               <xsl:variable name="x_val0">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val0">
                 <xsl:value-of select="round(($var_beg)-((($yval_min)-(self::node()))*($var_mult)))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val0,'','',$y_val0,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path0} {$x_val0},{($var_beg)} {$margin_left},{($var_beg)}" style="fill:limegreen;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path1">
             <xsl:for-each select="ROWSET/ROW/C_EVENT1">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val1">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val1">
                 <xsl:value-of select="round(($var_beg)-((($yval_min)-(self::node()))*($var_mult)))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val1,'','',$y_val1,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path0}{$v_path1}" style="fill:hotpink;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path2">
             <xsl:for-each select="ROWSET/ROW/C_EVENT2">
               <xsl:variable name="x_val2">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val2">
                 <xsl:value-of select="round(($var_beg)-((($yval_min)-(self::node()))*($var_mult)))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val2,'','',$y_val2,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path1}{$v_path2}" style="fill:indianred;stroke:none;stroke-width:1" />'
           )
   ||
   TO_CLOB(
          '<xsl:variable name="v_path3">
             <xsl:for-each select="ROWSET/ROW/C_EVENT3">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val3">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val3">
                 <xsl:value-of select="round(($var_beg)-((($yval_min)-(self::node()))*($var_mult)))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val3,'','',$y_val3,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path2}{$v_path3}" style="fill:olive;stroke:none;stroke-width:1" />'
           )
   ||
   TO_CLOB(
          '<xsl:variable name="v_path4">
             <xsl:for-each select="ROWSET/ROW/C_EVENT4">
               <xsl:variable name="x_val4">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val4">
                 <xsl:value-of select="round(($var_beg)-((($yval_min)-(self::node()))*($var_mult)))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val4,'','',$y_val4,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path3}{$v_path4}" style="fill:gray;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path5">
             <xsl:for-each select="ROWSET/ROW/C_EVENT5">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val5">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val5">
                 <xsl:value-of select="round(($var_beg)-((($yval_min)-(self::node()))*($var_mult)))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val5,'','',$y_val5,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path4}{$v_path5}" style="fill:sienna;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path6">
             <xsl:for-each select="ROWSET/ROW/C_EVENT6">
               <xsl:variable name="x_val6">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val6">
                 <xsl:value-of select="round(($var_beg)-((($yval_min)-(self::node()))*($var_mult)))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val6,'','',$y_val6,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path5}{$v_path6}" style="fill:orange;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path7">
             <xsl:for-each select="ROWSET/ROW/C_EVENT7">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val7">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val7">
                 <xsl:value-of select="round(($var_beg)-((($yval_min)-(self::node()))*($var_mult)))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val7,'','',$y_val7,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path6}{$v_path7}" style="fill:tan;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path8">
             <xsl:for-each select="ROWSET/ROW/C_EVENT8">
               <xsl:variable name="x_val8">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val8">
                 <xsl:value-of select="round(($var_beg)-((($yval_min)-(self::node()))*($var_mult)))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val8,'','',$y_val8,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path7}{$v_path8}" style="fill:royalblue;stroke:none;stroke-width:1" />'
           )
   ||
   TO_CLOB(
          '<xsl:variable name="v_path9">
             <xsl:for-each select="ROWSET/ROW/C_EVENT9">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val9">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val9">
                 <xsl:value-of select="round(($var_beg)-((($yval_min)-(self::node()))*($var_mult)))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val9,'','',$y_val9,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path8}{$v_path9}" style="fill:skyblue;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path10">
             <xsl:for-each select="ROWSET/ROW/C_EVENT10">
               <xsl:variable name="x_val10">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val10">
                 <xsl:value-of select="round(($var_beg)-((($yval_min)-(self::node()))*($var_mult)))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val10,'','',$y_val10,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path9}{$v_path10}" style="fill:lightcyan;stroke:none;stroke-width:1" />'
           )
   ||
   TO_CLOB(
          '<xsl:variable name="v_path11">
             <xsl:for-each select="ROWSET/ROW/C_EVENT11">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val11">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val11">
                 <xsl:value-of select="round(($var_beg)-((($yval_min)-(self::node()))*($var_mult)))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val11,'','',$y_val11,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path10}{$v_path11}" style="fill:lightgray;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path12">
             <xsl:for-each select="ROWSET/ROW/C_EVENT12">
               <xsl:variable name="x_val12">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val12">
                 <xsl:value-of select="round(($var_beg)-((($yval_min)-(self::node()))*($var_mult)))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val12,'','',$y_val12,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path11}{$v_path12}" style="fill:bisque;stroke:none;stroke-width:1" />
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+5}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="/descendant::EVENT_NAME0[position()=1]"/></text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+0}" width="{10}" height="{6}" fill="limegreen" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+13}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="/descendant::EVENT_NAME1[position()=1]"/></text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+8}" width="{10}" height="{6}" fill="hotpink" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+21}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="/descendant::EVENT_NAME2[position()=1]"/></text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+16}" width="{10}" height="{6}" fill="indianred" stroke="black"/>   
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+29}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="/descendant::EVENT_NAME3[position()=1]"/></text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+24}" width="{10}" height="{6}" fill="olive" stroke="black"/>   
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+37}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="/descendant::EVENT_NAME4[position()=1]"/></text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+32}" width="{10}" height="{6}" fill="gray" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+45}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="/descendant::EVENT_NAME5[position()=1]"/></text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+40}" width="{10}" height="{6}" fill="sienna" stroke="black"/>'
           ) 
    || 
    TO_CLOB(
          '<text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+53}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="/descendant::EVENT_NAME6[position()=1]"/></text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+48}" width="{10}" height="{6}" fill="orange" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+61}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="/descendant::EVENT_NAME7[position()=1]"/></text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+56}" width="{10}" height="{6}" fill="tan" stroke="black"/>  
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+69}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="/descendant::EVENT_NAME8[position()=1]"/></text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+64}" width="{10}" height="{6}" fill="royalblue" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+77}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="/descendant::EVENT_NAME9[position()=1]"/></text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+72}" width="{10}" height="{6}" fill="skyblue" stroke="black"/>
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+85}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="/descendant::EVENT_NAME10[position()=1]"/></text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+80}" width="{10}" height="{6}" fill="lightcyan" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+93}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="/descendant::EVENT_NAME11[position()=1]"/></text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+88}" width="{10}" height="{6}" fill="lightgray" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+101}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="/descendant::EVENT_NAME12[position()=1]"/></text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+96}" 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_24d

Remarks:

  • The query has been executed from the CDB$ROOT container by the C##LSS common user,
  • The v$session_activity_lss has been created from the CDB$ROOT container in the C##LSS schema,
  • The views defined in the part XXI to part XXIII could be modified in order to use v$active_session_history (ASH) if available and licensed,
  • The view v$session_activity_lss is a session id consolidation e.g. it might exist several sessions in different CDB/PDBs with the same session id.

Generating SVG graphics with SQL*Plus – Part XXIII – Horizontal stacked bar graph – Top Activity Sessions – Light Sampling Sessions – CDB database

Scope

It could be interesting to have the top activity sessions of a whole CDB database e.g. through all the CDB/PDB. We will limit to the top 20 activity sessions. For each session we will display:

  • Session Id,
  • Activity,
  • User Name,
  • Program Name,
  • Container Name.

Remark: The maximum value of the ‘Activity’ field is linked to the maximum activity session during the last 10 minutes interval.

We will create a view in order to display the top activity sessions.

View creation – Step 1

For the last 10 minutes, we will count the number of active sessions that are linked to a wait class or a cpu event as well as the total number of events per session id/serial# as follow:

        SELECT sid,
               serial#,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),-1,1)) count_cpu,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),0,1))  count_other,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),1,1))  count_application,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),2,1))  count_configuration,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),3,1))  count_administrative,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),4,1))  count_concurrency,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),5,1))  count_commit,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),7,1))  count_network,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),8,1))  count_user_io,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),9,1))  count_system_io,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),10,1)) count_scheduler,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),11,1)) count_cluster,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),12,1)) count_queueing,
               COUNT(*)                             count_total,
               MAX(lss_sample.nb_samples)           max_samples,
               MAX(user#)                           max_user#,
               MAX(program)                         max_program,
               MAX(con_id)                          max_con_id
        FROM lss$_sampling_session
        CROSS JOIN 
           (SELECT MAX(sample_id) - MIN(sample_id)  nb_samples
            FROM lss$_sampling_session
            WHERE sample_time >= SYSDATE -(10/24/60)
           ) lss_sample
        WHERE sample_time >= SYSDATE -(10/24/60)
        GROUP BY sid,
                 serial#
        ORDER BY count_total DESC
        FETCH FIRST 20 ROWS ONLY

Remarks:

  • The Cross Join query computes the number of samples during the last 10 minutes,
  • We have used the clause ‘FETCH FIRST 20 ROWS ONLY’ in order to have only the top 20.

View creation – Step 2

For the top 20 activity sessions, we will define for each session in average how much it is waiting on such or such wait class and how much it is using cpu as follow:

     SELECT sid,
           serial#,
           max_user#   user#,
           max_program user_program,
           max_con_id  user_con_id,
           TRUNC((count_cpu/(max_samples+1)),3)            aas1,  --aas_cpu
           TRUNC((count_other/(max_samples+1)),3)          aas2,  --aas_other
           TRUNC((count_application/(max_samples+1)),3)    aas3,  --aas_application
           TRUNC((count_configuration/(max_samples+1)),3)  aas4,  --aas_configuration
           TRUNC((count_administrative/(max_samples+1)),3) aas5,  --aas_administrative
           TRUNC((count_concurrency/(max_samples+1)),3)    aas6,  --aas_concurrency
           TRUNC((count_commit/(max_samples+1)),3)         aas7,  --aas_commit
           TRUNC((count_network/(max_samples+1)),3)        aas8,  --aas_network
           TRUNC((count_user_io/(max_samples+1)),3)        aas9,  --aas_user_io
           TRUNC((count_system_io/(max_samples+1)),3)      aas10, --aas_system_io
           TRUNC((count_scheduler/(max_samples+1)),3)      aas11, --aas_scheduler
           TRUNC((count_cluster/(max_samples+1)),3)        aas12, --aas_cluster
           TRUNC((count_queueing/(max_samples+1)),3)       aas13, --aas_queueing 
           count_total
    FROM
       (SELECT sid,
               serial#,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),-1,1)) count_cpu,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),0,1))  count_other,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),1,1))  count_application,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),2,1))  count_configuration,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),3,1))  count_administrative,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),4,1))  count_concurrency,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),5,1))  count_commit,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),7,1))  count_network,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),8,1))  count_user_io,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),9,1))  count_system_io,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),10,1)) count_scheduler,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),11,1)) count_cluster,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),12,1)) count_queueing,
               COUNT(*)                             count_total,
               MAX(lss_sample.nb_samples)           max_samples,
               MAX(user#)                           max_user#,
               MAX(program)                         max_program,
               MAX(con_id)                          max_con_id
        FROM lss$_sampling_session
        CROSS JOIN 
           (SELECT MAX(sample_id) - MIN(sample_id)  nb_samples
            FROM lss$_sampling_session
            WHERE sample_time >= SYSDATE -(10/24/60)
           ) lss_sample
        WHERE sample_time >= SYSDATE -(10/24/60)
        GROUP BY sid,
                 serial#
        ORDER BY count_total DESC
        FETCH FIRST 20 ROWS ONLY
        )

View creation – Step 3

Finally we will accumulate the different wait classes and cpu AAS for the top 20 activity sessions as follow:

CREATE OR REPLACE VIEW v$top_activity_session_lss
AS
SELECT sid,
       serial#,
       user#,
       user_program,
       user_con_id,
       count_total,
       aas1                                                                 C_CPU,
       aas1+aas2                                                            C_OTHER,
       aas1+aas2+aas3                                                       C_APPLICATION,
       aas1+aas2+aas3+aas4                                                  C_CONFIGURATION,
       aas1+aas2+aas3+aas4+aas5                                             C_ADMINISTRATIVE,
       aas1+aas2+aas3+aas4+aas5+aas6                                        C_CONCURRENCY,
       aas1+aas2+aas3+aas4+aas5+aas6+aas7                                   C_COMMIT,
       aas1+aas2+aas3+aas4+aas5+aas6+aas7+aas8                              C_NETWORK,
       aas1+aas2+aas3+aas4+aas5+aas6+aas7+aas8+aas9                         C_USER_IO,
       aas1+aas2+aas3+aas4+aas5+aas6+aas7+aas8+aas9+aas10                   C_SYSTEM_IO,
       aas1+aas2+aas3+aas4+aas5+aas6+aas7+aas8+aas9+aas10+aas11             C_SCHEDULER,
       aas1+aas2+aas3+aas4+aas5+aas6+aas7+aas8+aas9+aas10+aas11+aas12       C_CLUSTER,
       aas1+aas2+aas3+aas4+aas5+aas6+aas7+aas8+aas9+aas10+aas11+aas12+aas13 C_QUEUEING,
       MAX(aas1+aas2+aas3+aas4+aas5+aas6+aas7+aas8+aas9+aas10+aas11+aas12+aas13) OVER() MAX_AAS
FROM 
   (SELECT sid,
           serial#,
           max_user#   user#,
           max_program user_program,
           max_con_id  user_con_id,
           TRUNC((count_cpu/(max_samples+1)),3)            aas1,  --aas_cpu
           TRUNC((count_other/(max_samples+1)),3)          aas2,  --aas_other
           TRUNC((count_application/(max_samples+1)),3)    aas3,  --aas_application
           TRUNC((count_configuration/(max_samples+1)),3)  aas4,  --aas_configuration
           TRUNC((count_administrative/(max_samples+1)),3) aas5,  --aas_administrative
           TRUNC((count_concurrency/(max_samples+1)),3)    aas6,  --aas_concurrency
           TRUNC((count_commit/(max_samples+1)),3)         aas7,  --aas_commit
           TRUNC((count_network/(max_samples+1)),3)        aas8,  --aas_network
           TRUNC((count_user_io/(max_samples+1)),3)        aas9,  --aas_user_io
           TRUNC((count_system_io/(max_samples+1)),3)      aas10, --aas_system_io
           TRUNC((count_scheduler/(max_samples+1)),3)      aas11, --aas_scheduler
           TRUNC((count_cluster/(max_samples+1)),3)        aas12, --aas_cluster
           TRUNC((count_queueing/(max_samples+1)),3)       aas13, --aas_queueing 
           count_total
    FROM
       (SELECT sid,
               serial#,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),-1,1)) count_cpu,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),0,1))  count_other,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),1,1))  count_application,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),2,1))  count_configuration,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),3,1))  count_administrative,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),4,1))  count_concurrency,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),5,1))  count_commit,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),7,1))  count_network,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),8,1))  count_user_io,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),9,1))  count_system_io,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),10,1)) count_scheduler,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),11,1)) count_cluster,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),12,1)) count_queueing,
               COUNT(*)                             count_total,
               MAX(lss_sample.nb_samples)           max_samples,
               MAX(user#)                           max_user#,
               MAX(program)                         max_program,
               MAX(con_id)                          max_con_id
        FROM lss$_sampling_session
        CROSS JOIN 
           (SELECT MAX(sample_id) - MIN(sample_id)  nb_samples
            FROM lss$_sampling_session
            WHERE sample_time >= SYSDATE -(10/24/60)
           ) lss_sample
        WHERE sample_time >= SYSDATE -(10/24/60)
        GROUP BY sid,
                 serial#
        ORDER BY count_total DESC
        FETCH FIRST 20 ROWS ONLY
        )
   );

Modified source query

We will modify the source query as follow:

        SELECT top_act.sid              SID
        ,      DECODE(top_act.user#,0,'SYS',1,'PUBLIC',cdb_users.username) USERNAME
        ,      top_act.user_program     USER_PROGRAM
        ,      DECODE(top_act.user_con_id,0,'CDB WIDE',cont.name) CONTAINER_NAME
        ,      top_act.c_cpu            C_CPU
        ,      top_act.c_other          C_OTHER
        ,      top_act.c_application    C_APPLICATION
        ,      top_act.c_configuration  C_CONFIGURATION
        ,      top_act.c_administrative C_ADMINISTRATIVE
        ,      top_act.c_concurrency    C_CONCURRENCY
        ,      top_act.c_commit         C_COMMIT
        ,      top_act.c_network        C_NETWORK
        ,      top_act.c_user_io        C_USER_IO
        ,      top_act.c_system_io      C_SYSTEM_IO
        ,      top_act.c_scheduler      C_SCHEDULER
        ,      top_act.c_cluster        C_CLUSTER
        ,      top_act.c_queueing       C_QUEUEING
        ,      top_act.max_aas          MAX_AAS
        FROM v$top_activity_session_lss top_act
        LEFT OUTER JOIN cdb_users 
          ON cdb_users.user_id = top_act.user#
         AND cdb_users.con_id = top_act.user_con_id
        LEFT OUTER JOIN v$containers cont
          ON cont.con_id = top_act.user_con_id
        ORDER BY top_act.count_total DESC, top_act.c_queueing DESC

In order to display the container name and the user name, we are using the v$containers and the cdb_users views. However, because the v$containers and cdb_users are views that contain data linked to several containers (CDB$ROOT, PDB’s) and because the common user C##LSS should see data of all those containers, we will set the CONTAINER_DATA attribute as follow:

SYS@orcl> ALTER USER C##LSS
  2  SET CONTAINER_DATA = (CDB$ROOT,PDB1)
  3  FOR v_$containers CONTAINER=CURRENT;

User altered.

SYS@orcl>

SYS@orcl> ALTER USER C##LSS
  2  SET CONTAINER_DATA = (CDB$ROOT,PDB1)
  3  FOR cdb_users CONTAINER=CURRENT;

User altered.

We have only restricted to the containers CDB$ROOT and PDB1.

XSLT processing

We will use the query defined in the part XVI as a starting point with the main following differences:

  • The X axis time value will be replaced by a session id value,
  • The graph bars will be horizontal instead of vertical in this case.

XSLT variables

We will add five additional variables in the XSLT document:

  • <xsl:variable name="bar_height">10</xsl:variable>

    Height of the horizontal bar,

  • <xsl:variable name="length_width">150</xsl:variable>

    Length of the horizontal bar,

  • <xsl:variable name="xval_min">0</xsl:variable>

    Minimun activity value,

  • <xsl:variable name="xval_max"><xsl:value-of select="/descendant::MAX_AAS[position()=1]"/>

    First value of the column MAX_AAS,

  • <xsl:variable name="session_nb"><xsl:value-of select="count(/descendant::SID)"/></xsl:variable>

    Number of occurrence of the column SID.

Furthermore:

  • The variable “margin_top” is set to 30,
  • The variable “margin_left” is set to 45,
  • The variable “graph_width” is set to ‘$length_width+$margin_left+$margin_right+210’,
  • The variable “graph_height” is set to ‘270+$margin_top+$margin_bottom’,
  • The variable “graph_name” is set to ‘LSS Top Activity Sessions (last 10 minutes) – CDB/PDB’.

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_23f.svg

SELECT XMLTRANSFORM
   (DBMS_XMLGEN.GETXMLTYPE
      ('SELECT top_act.sid              SID
        ,      DECODE(top_act.user#,0,''SYS'',1,''PUBLIC'',cdb_users.username) USERNAME
        ,      top_act.user_program     USER_PROGRAM
        ,      DECODE(top_act.user_con_id,0,''CDB WIDE'',cont.name) CONTAINER_NAME
        ,      top_act.c_cpu            C_CPU
        ,      top_act.c_other          C_OTHER
        ,      top_act.c_application    C_APPLICATION
        ,      top_act.c_configuration  C_CONFIGURATION
        ,      top_act.c_administrative C_ADMINISTRATIVE
        ,      top_act.c_concurrency    C_CONCURRENCY
        ,      top_act.c_commit         C_COMMIT
        ,      top_act.c_network        C_NETWORK
        ,      top_act.c_user_io        C_USER_IO
        ,      top_act.c_system_io      C_SYSTEM_IO
        ,      top_act.c_scheduler      C_SCHEDULER
        ,      top_act.c_cluster        C_CLUSTER
        ,      top_act.c_queueing       C_QUEUEING
        ,      top_act.max_aas          MAX_AAS
        FROM v$top_activity_session_lss top_act
        LEFT OUTER JOIN cdb_users 
          ON cdb_users.user_id = top_act.user#
         AND cdb_users.con_id = top_act.user_con_id
        LEFT OUTER JOIN v$containers cont
          ON cont.con_id = top_act.user_con_id
        ORDER BY top_act.count_total DESC, top_act.c_queueing DESC')
,      XMLTYPE.CREATEXML
   (TO_CLOB(
    '<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
     <xsl:variable name="margin_top">30</xsl:variable>
     <xsl:variable name="margin_bottom">30</xsl:variable>
     <xsl:variable name="margin_left">45</xsl:variable>
     <xsl:variable name="margin_right">100</xsl:variable>
     <xsl:variable name="bar_height">10</xsl:variable>
     <xsl:variable name="length_width">150</xsl:variable>
     <xsl:variable name="graph_width"><xsl:value-of select="$length_width+$margin_left+$margin_right+210"/></xsl:variable>
     <xsl:variable name="graph_height"><xsl:value-of select="270+$margin_top+$margin_bottom"/></xsl:variable>
     <xsl:variable name="graph_name">LSS Top Activity Sessions (last 10 minutes) - CDB/PDB</xsl:variable>
     <xsl:variable name="xval_min">0</xsl:variable>
     <xsl:variable name="xval_max"><xsl:value-of select="/descendant::MAX_AAS[position()=1]"/></xsl:variable>
     <xsl:variable name="session_nb"><xsl:value-of select="count(/descendant::SID)"/></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)-20}" style="fill: #000000; stroke: none;font-size:10px;text-anchor=start"><xsl:value-of select="$graph_name"/></text>
           <text x="{($margin_left)-35}" y="{($margin_top)-5}" style="fill: #000000; stroke: none;font-size:8px;font-weight:bold;text-anchor=start">Session Id</text>
           <text x="{($margin_left)+1}" y="{($margin_top)-5}" style="fill: #000000; stroke: none;font-size:8px;font-weight:bold;text-anchor=start">Activity</text>
           <text x="{($margin_left)+160}" y="{($margin_top)-5}" style="fill: #000000; stroke: none;font-size:8px;font-weight:bold;text-anchor=start">User Name</text>
           <text x="{($margin_left)+240}" y="{($margin_top)-5}" style="fill: #000000; stroke: none;font-size:8px;font-weight:bold;text-anchor=start">Program Name</text>
           <text x="{($margin_left)+325}" y="{($margin_top)-5}" style="fill: #000000; stroke: none;font-size:8px;font-weight:bold;text-anchor=start">Container</text>
           <line x1="{($margin_left)-35}" y1="{($margin_top)-2+(($bar_height)+5)*(position()-1)}" x2="{($graph_width)-($margin_right)+10}" y2="{($margin_top)-2+(($bar_height)+5)*(position()-1)}" style="stroke:lightblue;stroke-width:1" />'
           ) 
    || 
    TO_CLOB(
          '<xsl:for-each select="ROWSET/ROW">
             <rect x="{($margin_left)}" y="{$margin_top+(($bar_height)+5)*(position()-1)}" width="{((($xval_min)-(descendant::C_CPU))*(($length_width) div (($xval_min)-($xval_max))))}" height="{$bar_height}" fill="limegreen" stroke="none"/> 
             <rect x="{((($xval_min)-(descendant::C_CPU))*(($length_width) div (($xval_min)-($xval_max))))+($margin_left)}" y="{$margin_top+(($bar_height)+5)*(position()-1)}" width="{(((descendant::C_CPU)-(C_OTHER))*(($length_width) div (($xval_min)-($xval_max))))}" height="{$bar_height}" fill="hotpink" stroke="none"/>
             <rect x="{((($xval_min)-(descendant::C_OTHER))*(($length_width) div (($xval_min)-($xval_max))))+($margin_left)}" y="{$margin_top+(($bar_height)+5)*(position()-1)}" width="{(((descendant::C_OTHER)-(C_APPLICATION))*(($length_width) div (($xval_min)-($xval_max))))}" height="{$bar_height}" fill="indianred" stroke="none"/>                                                                                                                                    
             <rect x="{((($xval_min)-(descendant::C_APPLICATION))*(($length_width) div (($xval_min)-($xval_max))))+($margin_left)}" y="{$margin_top+(($bar_height)+5)*(position()-1)}" width="{(((descendant::C_APPLICATION)-(C_CONFIGURATION))*(($length_width) div (($xval_min)-($xval_max))))}" height="{$bar_height}" fill="olive" stroke="none"/>   
             <rect x="{((($xval_min)-(descendant::C_CONFIGURATION))*(($length_width) div (($xval_min)-($xval_max))))+($margin_left)}" y="{$margin_top+(($bar_height)+5)*(position()-1)}" width="{(((descendant::C_CONFIGURATION)-(C_ADMINISTRATIVE))*(($length_width) div (($xval_min)-($xval_max))))}" height="{$bar_height}" fill="grey" stroke="none"/>   
             <rect x="{((($xval_min)-(descendant::C_ADMINISTRATIVE))*(($length_width) div (($xval_min)-($xval_max))))+($margin_left)}" y="{$margin_top+(($bar_height)+5)*(position()-1)}" width="{(((descendant::C_ADMINISTRATIVE)-(C_CONCURRENCY))*(($length_width) div (($xval_min)-($xval_max))))}" height="{$bar_height}" fill="sienna" stroke="none"/>'
           ) 
    || 
    TO_CLOB(
          '  <rect x="{((($xval_min)-(descendant::C_CONCURRENCY))*(($length_width) div (($xval_min)-($xval_max))))+($margin_left)}" y="{$margin_top+(($bar_height)+5)*(position()-1)}" width="{(((descendant::C_CONCURRENCY)-(C_COMMIT))*(($length_width) div (($xval_min)-($xval_max))))}" height="{$bar_height}" fill="orange" stroke="none"/>  
             <rect x="{((($xval_min)-(descendant::C_COMMIT))*(($length_width) div (($xval_min)-($xval_max))))+($margin_left)}" y="{$margin_top+(($bar_height)+5)*(position()-1)}" width="{(((descendant::C_COMMIT)-(C_NETWORK))*(($length_width) div (($xval_min)-($xval_max))))}" height="{$bar_height}" fill="tan" stroke="none"/>   
             <rect x="{((($xval_min)-(descendant::C_NETWORK))*(($length_width) div (($xval_min)-($xval_max))))+($margin_left)}" y="{$margin_top+(($bar_height)+5)*(position()-1)}" width="{(((descendant::C_NETWORK)-(C_USER_IO))*(($length_width) div (($xval_min)-($xval_max))))}" height="{$bar_height}" fill="royalblue" stroke="none"/>   
             <rect x="{((($xval_min)-(descendant::C_USER_IO))*(($length_width) div (($xval_min)-($xval_max))))+($margin_left)}" y="{$margin_top+(($bar_height)+5)*(position()-1)}" width="{(((descendant::C_USER_IO)-(C_SYSTEM_IO))*(($length_width) div (($xval_min)-($xval_max))))}" height="{$bar_height}" fill="skyblue" stroke="none"/>   
             <rect x="{((($xval_min)-(descendant::C_SYSTEM_IO))*(($length_width) div (($xval_min)-($xval_max))))+($margin_left)}" y="{$margin_top+(($bar_height)+5)*(position()-1)}" width="{(((descendant::C_SYSTEM_IO)-(C_SCHEDULER))*(($length_width) div (($xval_min)-($xval_max))))}" height="{$bar_height}" fill="lightcyan" stroke="none"/>   
             <rect x="{((($xval_min)-(descendant::C_SCHEDULER))*(($length_width) div (($xval_min)-($xval_max))))+($margin_left)}" y="{$margin_top+(($bar_height)+5)*(position()-1)}" width="{(((descendant::C_SCHEDULER)-(C_CLUSTER))*(($length_width) div (($xval_min)-($xval_max))))}" height="{$bar_height}" fill="lightgray" stroke="none"/>   
             <rect x="{((($xval_min)-(descendant::C_CLUSTER))*(($length_width) div (($xval_min)-($xval_max))))+($margin_left)}" y="{$margin_top+(($bar_height)+5)*(position()-1)}" width="{(((descendant::C_CLUSTER)-(C_QUEUEING))*(($length_width) div (($xval_min)-($xval_max))))}" height="{$bar_height}" fill="bisque" stroke="none"/> 
             <text x="{($margin_left)-25}" y="{$margin_top+8+(($bar_height)+5)*(position()-1)}" style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="(descendant::SID)"/></text>
             <text x="{($margin_left)+160}" y="{$margin_top+8+(($bar_height)+5)*(position()-1)}" style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="(descendant::USERNAME)"/></text>
             <text x="{($margin_left)+240}" y="{$margin_top+8+(($bar_height)+5)*(position()-1)}" style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="(descendant::USER_PROGRAM)"/></text>
             <text x="{($margin_left)+325}" y="{$margin_top+8+(($bar_height)+5)*(position()-1)}" style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="(descendant::CONTAINER_NAME)"/></text>
             <line x1="{($margin_left)-35}" y1="{($margin_top)-2+(($bar_height)+5)*(position()-0)}" x2="{($graph_width)-($margin_right)+10}" y2="{($margin_top)-2+(($bar_height)+5)*(position()-0)}" style="stroke:lightblue;stroke-width:1" />
           </xsl:for-each>'
           ) 
    || 
    TO_CLOB(
          '<text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+0}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">CPU</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)-5}" width="{10}" height="{6}" fill="limegreen" stroke="black"/> 
           <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"/>'
           ) 
    || 
    TO_CLOB(
          '<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"/>
           <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_23f1

Remarks:

  • The query has been executed from the CDB$ROOT container by the C##LSS common user,
  • The v$top_activity_session_lss has been created from the CDB$ROOT container in the C##LSS schema.

Generating SVG graphics with SQL*Plus – Part XXII – Stacked area graph – Average Active Sessions – Light Sampling Sessions – CDB/PDB splitting

Scope

In the previous post we have displayed the average active sessions for the last hour at the CDB level e.g. from the CDB$ROOT container through all the PDBs. It could be interesting to have a CDB/PDB splitting. We will limit this CDB/PDB splitting to the following containers:

  • CDB Wide e.g. con_id=0,
  • CDB$ROOT (con_id=1),
  • PDB1 (con_id=3) to PDB4 (cond_id=6).

For each CDB/PDB we will display the average active sessions linked to the CPU events and the wait class events. We will create a view in order to display the average active sessions for the CDB/PDB.

View creation – Step 1

Every minute we will count the number of active sessions that are linked to the wait classes or a cpu event for each container as follow:

SELECT TO_CHAR(sample_time,'YYYYMMDDHH24MI') sample_yyyymmddhhmi,
       con_id,
       COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),-1,1)) count_cpu,
       COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),0,1,1,1,2,1,3,1,4,1,5,1,7,1,8,1,9,1,10,1,11,1,12,1)) count_wait
       FROM lss$_sampling_session
       GROUP BY con_id,
                TO_CHAR(sample_time,'YYYYMMDDHH24MI')

View creation – Step 2

We must then compute the number of samples during the minute interval:

                SELECT TO_CHAR(sample_time,'YYYYMMDDHH24MI') sample_yyyymmddhhmi,
                       con_id,
                       MAX(lss_sample.nb_samples) nb_samples,
                       COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),-1,1)) count_cpu,
                       COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),0,1,1,1,2,1,3,1,4,1,5,1,7,1,8,1,9,1,10,1,11,1,12,1)) count_wait
                FROM lss$_sampling_session
                INNER JOIN 
                   (SELECT TO_CHAR(sample_time,'YYYYMMDDHH24MI') sample_yyyymmddhhmi,
                           MAX(sample_id) - MIN(sample_id)       nb_samples
                    FROM lss$_sampling_session
                    GROUP BY TO_CHAR(sample_time,'YYYYMMDDHH24MI')
                    ) lss_sample
                  ON lss_sample.sample_yyyymmddhhmi = TO_CHAR(lss$_sampling_session.sample_time,'YYYYMMDDHH24MI')
                GROUP BY con_id,
                        TO_CHAR(sample_time,'YYYYMMDDHH24MI')

View creation – Step 3

To define how many sessions in average are waiting on the wait classes or are using cpu during a minute in a container, we will count the wait class and the cpu events on a period of time of one minute for each container and we will divide by the number of samples plus one as follow:

            SELECT sample_yyyymmddhhmi,
                   CASE con_id
                      WHEN 0 THEN TRUNC(count_cpu/(nb_samples+1),3)
                      ELSE 0
                   END aas_cpu0,
                   CASE con_id
                      WHEN 0 THEN TRUNC(count_wait/(nb_samples+1),3)
                      ELSE 0
                   END aas_wait0,
                   CASE con_id
                      WHEN 1 THEN TRUNC(count_cpu/(nb_samples+1),3)
                      ELSE 0
                   END aas_cpu1,
                   CASE con_id
                      WHEN 1 THEN TRUNC(count_wait/(nb_samples+1),3)
                      ELSE 0
                   END aas_wait1,
                   CASE con_id
                      WHEN 3 THEN TRUNC(count_cpu/(nb_samples+1),3)
                      ELSE 0
                   END aas_cpu2,
                   CASE con_id
                      WHEN 3 THEN TRUNC(count_wait/(nb_samples+1),3)
                      ELSE 0
                   END aas_wait2,
                   CASE con_id
                      WHEN 4 THEN TRUNC(count_cpu/(nb_samples+1),3)
                      ELSE 0
                   END aas_cpu3,
                   CASE con_id
                      WHEN 4 THEN TRUNC(count_wait/(nb_samples+1),3)
                      ELSE 0
                   END aas_wait3,
                   CASE con_id
                      WHEN 5 THEN TRUNC(count_cpu/(nb_samples+1),3)
                      ELSE 0
                   END aas_cpu4,
                   CASE con_id
                      WHEN 5 THEN TRUNC(count_wait/(nb_samples+1),3)
                      ELSE 0
                   END aas_wait4,
                   CASE con_id
                      WHEN 6 THEN TRUNC(count_cpu/(nb_samples+1),3)
                      ELSE 0
                   END aas_cpu5,
                   CASE con_id
                      WHEN 6 THEN TRUNC(count_wait/(nb_samples+1),3)
                      ELSE 0
                   END aas_wait5
            FROM 
               (SELECT TO_CHAR(sample_time,'YYYYMMDDHH24MI') sample_yyyymmddhhmi,
                       con_id,
                       MAX(lss_sample.nb_samples) nb_samples,
                       COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),-1,1)) count_cpu,
                       COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),0,1,1,1,2,1,3,1,4,1,5,1,7,1,8,1,9,1,10,1,11,1,12,1)) count_wait
                FROM lss$_sampling_session
                INNER JOIN 
                   (SELECT TO_CHAR(sample_time,'YYYYMMDDHH24MI') sample_yyyymmddhhmi,
                           MAX(sample_id) - MIN(sample_id)       nb_samples
                    FROM lss$_sampling_session
                    GROUP BY TO_CHAR(sample_time,'YYYYMMDDHH24MI')
                    ) lss_sample
                  ON lss_sample.sample_yyyymmddhhmi = TO_CHAR(lss$_sampling_session.sample_time,'YYYYMMDDHH24MI')
                GROUP BY con_id,
                        TO_CHAR(sample_time,'YYYYMMDDHH24MI')
                )

Remark: We have restricted the containers to con_id={0,1} and con_id={3,4,5,6}

View creation – Step 4

We will then sum for each selected container, the number of active sessions linked to the wait classes or a cpu event as follow:

        SELECT sample_yyyymmddhhmi,
               SUM(aas_cpu0)  sum_aas_cpu0,
               SUM(aas_wait0) sum_aas_wait0,
               SUM(aas_cpu1)  sum_aas_cpu1,
               SUM(aas_wait1) sum_aas_wait1,
               SUM(aas_cpu2)  sum_aas_cpu2,
               SUM(aas_wait2) sum_aas_wait2,
               SUM(aas_cpu3)  sum_aas_cpu3,
               SUM(aas_wait3) sum_aas_wait3,
               SUM(aas_cpu4)  sum_aas_cpu4,
               SUM(aas_wait4) sum_aas_wait4,
               SUM(aas_cpu5)  sum_aas_cpu5,
               SUM(aas_wait5) sum_aas_wait5
        FROM 
           (SELECT sample_yyyymmddhhmi,
                   CASE con_id
                      WHEN 0 THEN TRUNC(count_cpu/(nb_samples+1),3)
                      ELSE 0
                   END aas_cpu0,
                   CASE con_id
                      WHEN 0 THEN TRUNC(count_wait/(nb_samples+1),3)
                      ELSE 0
                   END aas_wait0,
                   CASE con_id
                      WHEN 1 THEN TRUNC(count_cpu/(nb_samples+1),3)
                      ELSE 0
                   END aas_cpu1,
                   CASE con_id
                      WHEN 1 THEN TRUNC(count_wait/(nb_samples+1),3)
                      ELSE 0
                   END aas_wait1,
                   CASE con_id
                      WHEN 3 THEN TRUNC(count_cpu/(nb_samples+1),3)
                      ELSE 0
                   END aas_cpu2,
                   CASE con_id
                      WHEN 3 THEN TRUNC(count_wait/(nb_samples+1),3)
                      ELSE 0
                   END aas_wait2,
                   CASE con_id
                      WHEN 4 THEN TRUNC(count_cpu/(nb_samples+1),3)
                      ELSE 0
                   END aas_cpu3,
                   CASE con_id
                      WHEN 4 THEN TRUNC(count_wait/(nb_samples+1),3)
                      ELSE 0
                   END aas_wait3,
                   CASE con_id
                      WHEN 5 THEN TRUNC(count_cpu/(nb_samples+1),3)
                      ELSE 0
                   END aas_cpu4,
                   CASE con_id
                      WHEN 5 THEN TRUNC(count_wait/(nb_samples+1),3)
                      ELSE 0
                   END aas_wait4,
                   CASE con_id
                      WHEN 6 THEN TRUNC(count_cpu/(nb_samples+1),3)
                      ELSE 0
                   END aas_cpu5,
                   CASE con_id
                      WHEN 6 THEN TRUNC(count_wait/(nb_samples+1),3)
                      ELSE 0
                   END aas_wait5
            FROM 
               (SELECT TO_CHAR(sample_time,'YYYYMMDDHH24MI') sample_yyyymmddhhmi,
                       con_id,
                       MAX(lss_sample.nb_samples) nb_samples,
                       COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),-1,1)) count_cpu,
                       COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),0,1,1,1,2,1,3,1,4,1,5,1,7,1,8,1,9,1,10,1,11,1,12,1)) count_wait
                FROM lss$_sampling_session
                INNER JOIN 
                   (SELECT TO_CHAR(sample_time,'YYYYMMDDHH24MI') sample_yyyymmddhhmi,
                           MAX(sample_id) - MIN(sample_id)       nb_samples
                    FROM lss$_sampling_session
                    GROUP BY TO_CHAR(sample_time,'YYYYMMDDHH24MI')
                    ) lss_sample
                  ON lss_sample.sample_yyyymmddhhmi = TO_CHAR(lss$_sampling_session.sample_time,'YYYYMMDDHH24MI')
                GROUP BY con_id,
                        TO_CHAR(sample_time,'YYYYMMDDHH24MI')
                )
           ) GROUP BY sample_yyyymmddhhmi

View creation – Step 5

We will also handle the potential sampling process inactivity during the last hour as follow:

     SELECT NVL(co_base_qry.sample_yyyymmddhhmi,time_window.start_time) sample_yyyymmddhhmi,
           NVL(co_base_qry.sum_aas_cpu0,0)   aas_cpu0,
           NVL(co_base_qry.sum_aas_wait0,0)  aas_wait0,
           NVL(co_base_qry.sum_aas_cpu1,0)   aas_cpu1,
           NVL(co_base_qry.sum_aas_wait1,0)  aas_wait1,
           NVL(co_base_qry.sum_aas_cpu2,0)   aas_cpu2,
           NVL(co_base_qry.sum_aas_wait2,0)  aas_wait2,
           NVL(co_base_qry.sum_aas_cpu3,0)   aas_cpu3,
           NVL(co_base_qry.sum_aas_wait3,0)  aas_wait3,
           NVL(co_base_qry.sum_aas_cpu4,0)   aas_cpu4,
           NVL(co_base_qry.sum_aas_wait4,0)  aas_wait4,
           NVL(co_base_qry.sum_aas_cpu5,0)   aas_cpu5,
           NVL(co_base_qry.sum_aas_wait5,0)  aas_wait5
    FROM 
       (SELECT TO_CHAR(SYSDATE - (LEVEL/24/60),'YYYYMMDDHH24MI') start_time
        FROM DUAL 
        CONNECT BY LEVEL <= 61
       ) time_window
    LEFT OUTER JOIN 
       (SELECT sample_yyyymmddhhmi,
               SUM(aas_cpu0)  sum_aas_cpu0,
               SUM(aas_wait0) sum_aas_wait0,
               SUM(aas_cpu1)  sum_aas_cpu1,
               SUM(aas_wait1) sum_aas_wait1,
               SUM(aas_cpu2)  sum_aas_cpu2,
               SUM(aas_wait2) sum_aas_wait2,
               SUM(aas_cpu3)  sum_aas_cpu3,
               SUM(aas_wait3) sum_aas_wait3,
               SUM(aas_cpu4)  sum_aas_cpu4,
               SUM(aas_wait4) sum_aas_wait4,
               SUM(aas_cpu5)  sum_aas_cpu5,
               SUM(aas_wait5) sum_aas_wait5
        FROM 
           (SELECT sample_yyyymmddhhmi,
                   CASE con_id
                      WHEN 0 THEN TRUNC(count_cpu/(nb_samples+1),3)
                      ELSE 0
                   END aas_cpu0,
                   CASE con_id
                      WHEN 0 THEN TRUNC(count_wait/(nb_samples+1),3)
                      ELSE 0
                   END aas_wait0,
                   CASE con_id
                      WHEN 1 THEN TRUNC(count_cpu/(nb_samples+1),3)
                      ELSE 0
                   END aas_cpu1,
                   CASE con_id
                      WHEN 1 THEN TRUNC(count_wait/(nb_samples+1),3)
                      ELSE 0
                   END aas_wait1,
                   CASE con_id
                      WHEN 3 THEN TRUNC(count_cpu/(nb_samples+1),3)
                      ELSE 0
                   END aas_cpu2,
                   CASE con_id
                      WHEN 3 THEN TRUNC(count_wait/(nb_samples+1),3)
                      ELSE 0
                   END aas_wait2,
                   CASE con_id
                      WHEN 4 THEN TRUNC(count_cpu/(nb_samples+1),3)
                      ELSE 0
                   END aas_cpu3,
                   CASE con_id
                      WHEN 4 THEN TRUNC(count_wait/(nb_samples+1),3)
                      ELSE 0
                   END aas_wait3,
                   CASE con_id
                      WHEN 5 THEN TRUNC(count_cpu/(nb_samples+1),3)
                      ELSE 0
                   END aas_cpu4,
                   CASE con_id
                      WHEN 5 THEN TRUNC(count_wait/(nb_samples+1),3)
                      ELSE 0
                   END aas_wait4,
                   CASE con_id
                      WHEN 6 THEN TRUNC(count_cpu/(nb_samples+1),3)
                      ELSE 0
                   END aas_cpu5,
                   CASE con_id
                      WHEN 6 THEN TRUNC(count_wait/(nb_samples+1),3)
                      ELSE 0
                   END aas_wait5
            FROM 
               (SELECT TO_CHAR(sample_time,'YYYYMMDDHH24MI') sample_yyyymmddhhmi,
                       con_id,
                       MAX(lss_sample.nb_samples) nb_samples,
                       COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),-1,1)) count_cpu,
                       COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),0,1,1,1,2,1,3,1,4,1,5,1,7,1,8,1,9,1,10,1,11,1,12,1)) count_wait
                FROM lss$_sampling_session
                INNER JOIN 
                   (SELECT TO_CHAR(sample_time,'YYYYMMDDHH24MI') sample_yyyymmddhhmi,
                           MAX(sample_id) - MIN(sample_id)       nb_samples
                    FROM lss$_sampling_session
                    GROUP BY TO_CHAR(sample_time,'YYYYMMDDHH24MI')
                    ) lss_sample
                  ON lss_sample.sample_yyyymmddhhmi = TO_CHAR(lss$_sampling_session.sample_time,'YYYYMMDDHH24MI')
                GROUP BY con_id,
                        TO_CHAR(sample_time,'YYYYMMDDHH24MI')
                )
           ) GROUP BY sample_yyyymmddhhmi
       ) co_base_qry
      ON time_window.start_time=co_base_qry.sample_yyyymmddhhmi

View creation – Step 6

Finally we will accumulate the different wait class and cpu AAS values for the selected containers as follow:

CREATE OR REPLACE VIEW v$cdb_pdb_aas_lss
AS          
SELECT sample_yyyymmddhhmi,
       SUBSTR(sample_yyyymmddhhmi,9,2) || ':' || SUBSTR(sample_yyyymmddhhmi,11,2)                                        BEGIN_TIME,
       aas_cpu0                                                                                                          C_CONT0_CPU,
       aas_cpu0+aas_wait0                                                                                                C_CONT0_WAIT,
       aas_cpu0+aas_wait0+aas_cpu1                                                                                       C_CONT1_CPU,
       aas_cpu0+aas_wait0+aas_cpu1+aas_wait1                                                                             C_CONT1_WAIT,
       aas_cpu0+aas_wait0+aas_cpu1+aas_wait1+aas_cpu2                                                                    C_CONT2_CPU,
       aas_cpu0+aas_wait0+aas_cpu1+aas_wait1+aas_cpu2+aas_wait2                                                          C_CONT2_WAIT,
       aas_cpu0+aas_wait0+aas_cpu1+aas_wait1+aas_cpu2+aas_wait2+aas_cpu3                                                 C_CONT3_CPU,
       aas_cpu0+aas_wait0+aas_cpu1+aas_wait1+aas_cpu2+aas_wait2+aas_cpu3+aas_wait3                                       C_CONT3_WAIT,
       aas_cpu0+aas_wait0+aas_cpu1+aas_wait1+aas_cpu2+aas_wait2+aas_cpu3+aas_wait3+aas_cpu4                              C_CONT4_CPU,
       aas_cpu0+aas_wait0+aas_cpu1+aas_wait1+aas_cpu2+aas_wait2+aas_cpu3+aas_wait3+aas_cpu4+aas_wait4                    C_CONT4_WAIT,
       aas_cpu0+aas_wait0+aas_cpu1+aas_wait1+aas_cpu2+aas_wait2+aas_cpu3+aas_wait3+aas_cpu4+aas_wait4+aas_cpu5           C_CONT5_CPU,
       aas_cpu0+aas_wait0+aas_cpu1+aas_wait1+aas_cpu2+aas_wait2+aas_cpu3+aas_wait3+aas_cpu4+aas_wait4+aas_cpu5+aas_wait5 C_CONT5_WAIT,
       MAX(CEIL(aas_cpu0+aas_wait0+aas_cpu1+aas_wait1+aas_cpu2+aas_wait2+aas_cpu3+aas_wait3+aas_cpu4+aas_wait4+aas_cpu5+aas_wait5)) OVER() MAX_CONT_AAS
FROM 
   (SELECT NVL(co_base_qry.sample_yyyymmddhhmi,time_window.start_time) sample_yyyymmddhhmi,
           NVL(co_base_qry.sum_aas_cpu0,0)   aas_cpu0,
           NVL(co_base_qry.sum_aas_wait0,0)  aas_wait0,
           NVL(co_base_qry.sum_aas_cpu1,0)   aas_cpu1,
           NVL(co_base_qry.sum_aas_wait1,0)  aas_wait1,
           NVL(co_base_qry.sum_aas_cpu2,0)   aas_cpu2,
           NVL(co_base_qry.sum_aas_wait2,0)  aas_wait2,
           NVL(co_base_qry.sum_aas_cpu3,0)   aas_cpu3,
           NVL(co_base_qry.sum_aas_wait3,0)  aas_wait3,
           NVL(co_base_qry.sum_aas_cpu4,0)   aas_cpu4,
           NVL(co_base_qry.sum_aas_wait4,0)  aas_wait4,
           NVL(co_base_qry.sum_aas_cpu5,0)   aas_cpu5,
           NVL(co_base_qry.sum_aas_wait5,0)  aas_wait5
    FROM 
       (SELECT TO_CHAR(SYSDATE - (LEVEL/24/60),'YYYYMMDDHH24MI') start_time
        FROM DUAL 
        CONNECT BY LEVEL <= 61
       ) time_window
    LEFT OUTER JOIN 
       (SELECT sample_yyyymmddhhmi,
               SUM(aas_cpu0)  sum_aas_cpu0,
               SUM(aas_wait0) sum_aas_wait0,
               SUM(aas_cpu1)  sum_aas_cpu1,
               SUM(aas_wait1) sum_aas_wait1,
               SUM(aas_cpu2)  sum_aas_cpu2,
               SUM(aas_wait2) sum_aas_wait2,
               SUM(aas_cpu3)  sum_aas_cpu3,
               SUM(aas_wait3) sum_aas_wait3,
               SUM(aas_cpu4)  sum_aas_cpu4,
               SUM(aas_wait4) sum_aas_wait4,
               SUM(aas_cpu5)  sum_aas_cpu5,
               SUM(aas_wait5) sum_aas_wait5
        FROM 
           (SELECT sample_yyyymmddhhmi,
                   CASE con_id
                      WHEN 0 THEN TRUNC(count_cpu/(nb_samples+1),3)
                      ELSE 0
                   END aas_cpu0,
                   CASE con_id
                      WHEN 0 THEN TRUNC(count_wait/(nb_samples+1),3)
                      ELSE 0
                   END aas_wait0,
                   CASE con_id
                      WHEN 1 THEN TRUNC(count_cpu/(nb_samples+1),3)
                      ELSE 0
                   END aas_cpu1,
                   CASE con_id
                      WHEN 1 THEN TRUNC(count_wait/(nb_samples+1),3)
                      ELSE 0
                   END aas_wait1,
                   CASE con_id
                      WHEN 3 THEN TRUNC(count_cpu/(nb_samples+1),3)
                      ELSE 0
                   END aas_cpu2,
                   CASE con_id
                      WHEN 3 THEN TRUNC(count_wait/(nb_samples+1),3)
                      ELSE 0
                   END aas_wait2,
                   CASE con_id
                      WHEN 4 THEN TRUNC(count_cpu/(nb_samples+1),3)
                      ELSE 0
                   END aas_cpu3,
                   CASE con_id
                      WHEN 4 THEN TRUNC(count_wait/(nb_samples+1),3)
                      ELSE 0
                   END aas_wait3,
                   CASE con_id
                      WHEN 5 THEN TRUNC(count_cpu/(nb_samples+1),3)
                      ELSE 0
                   END aas_cpu4,
                   CASE con_id
                      WHEN 5 THEN TRUNC(count_wait/(nb_samples+1),3)
                      ELSE 0
                   END aas_wait4,
                   CASE con_id
                      WHEN 6 THEN TRUNC(count_cpu/(nb_samples+1),3)
                      ELSE 0
                   END aas_cpu5,
                   CASE con_id
                      WHEN 6 THEN TRUNC(count_wait/(nb_samples+1),3)
                      ELSE 0
                   END aas_wait5
            FROM 
               (SELECT TO_CHAR(sample_time,'YYYYMMDDHH24MI') sample_yyyymmddhhmi,
                       con_id,
                       MAX(lss_sample.nb_samples) nb_samples,
                       COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),-1,1)) count_cpu,
                       COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),0,1,1,1,2,1,3,1,4,1,5,1,7,1,8,1,9,1,10,1,11,1,12,1)) count_wait
                FROM lss$_sampling_session
                INNER JOIN 
                   (SELECT TO_CHAR(sample_time,'YYYYMMDDHH24MI') sample_yyyymmddhhmi,
                           MAX(sample_id) - MIN(sample_id)       nb_samples
                    FROM lss$_sampling_session
                    GROUP BY TO_CHAR(sample_time,'YYYYMMDDHH24MI')
                    ) lss_sample
                  ON lss_sample.sample_yyyymmddhhmi = TO_CHAR(lss$_sampling_session.sample_time,'YYYYMMDDHH24MI')
                GROUP BY con_id,
                        TO_CHAR(sample_time,'YYYYMMDDHH24MI')
                )
           ) GROUP BY sample_yyyymmddhhmi
       ) co_base_qry
      ON time_window.start_time=co_base_qry.sample_yyyymmddhhmi
   );

Modified source query

We will use the query defined in the part XXI as a starting point. We will modify the source query as follow:

        SELECT BEGIN_TIME,
               C_CONT0_CPU,
               C_CONT0_WAIT,
               C_CONT1_CPU,
               C_CONT1_WAIT,
               C_CONT2_CPU,
               C_CONT2_WAIT,
               C_CONT3_CPU,
               C_CONT3_WAIT,
               C_CONT4_CPU,
               C_CONT4_WAIT,
               C_CONT5_CPU,
               C_CONT5_WAIT,
               MAX_CONT_AAS,
               (SELECT value FROM v$parameter WHERE name='cpu_count') CPU_COUNT
        FROM v$cdb_pdb_aas_lss
        ORDER BY sample_yyyymmddhhmi

XSLT variables

  • The variable “graph_name” is set to ‘LSS Active Sessions – Waiting + Working – CDB/PDB splitting’,
  • The variable “yval_max” is set to the first value of the column MAX_CONT_AAS.

XSLT processing

The modification is the following:

  • The differents “for-each” “ROWSET/ROW/C_CPU” to “ROWSET/ROW/C_CLUSTER” have been replaced by “ROWSET/ROW/C_CONT0_CPU” to “ROWSET/ROW/C_CONT5_WAIT”.

Modified query

SET LINESIZE      2000
SET LONGCHUNKSIZE 30000
SET LONG          30000

SET FEEDBACK OFF
SET VERIFY   OFF
SET PAGESIZE 0

SET HEADING OFF

SPOOL generate_svg_22h.svg

SELECT XMLTRANSFORM
   (DBMS_XMLGEN.GETXMLTYPE
      ('SELECT BEGIN_TIME,
               C_CONT0_CPU,
               C_CONT0_WAIT,
               C_CONT1_CPU,
               C_CONT1_WAIT,
               C_CONT2_CPU,
               C_CONT2_WAIT,
               C_CONT3_CPU,
               C_CONT3_WAIT,
               C_CONT4_CPU,
               C_CONT4_WAIT,
               C_CONT5_CPU,
               C_CONT5_WAIT,
               MAX_CONT_AAS,
               (SELECT value FROM v$parameter WHERE name=''cpu_count'') CPU_COUNT
        FROM v$cdb_pdb_aas_lss
        ORDER BY sample_yyyymmddhhmi')
,      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">10</xsl:variable>
     <xsl:variable name="graph_width"><xsl:value-of select="600+$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">LSS Active Sessions - Waiting + Working - CDB/PDB splitting</xsl:variable>
     <xsl:variable name="graph_unit">Session Count</xsl:variable>
     <xsl:variable name="yval_max"><xsl:value-of select="/descendant::MAX_CONT_AAS[position()=1]"/></xsl:variable>
     <xsl:variable name="yval_min">0</xsl:variable>
     <xsl:variable name="cpu_count"><xsl:value-of select="/descendant::CPU_COUNT[position()=1]"/></xsl:variable>
       <xsl:template match="/">'
           )
    || 
    TO_CLOB(
         '<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)-24}" y="{($graph_height)-($margin_bottom)-2}"   style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="format-number(($yval_min),''00.00'')"/></text>
           <text x="{($margin_left)-24}" y="{($graph_height)-($margin_bottom)-25}"  style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="format-number((($yval_min)+(1*(($yval_max)-($yval_min)) div 4)),''00.00'')"/></text>
           <text x="{($margin_left)-24}" y="{($graph_height)-($margin_bottom)-50}"  style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="format-number((($yval_min)+((($yval_max)-($yval_min)) div 2)),''00.00'')"/></text>
           <text x="{($margin_left)-24}" y="{($graph_height)-($margin_bottom)-75}"  style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="format-number((($yval_min)+(3*(($yval_max)-($yval_min)) div 4)),''00.00'')"/></text>
           <text x="{($margin_left)-24}" y="{($graph_height)-($margin_bottom)-100}" style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="format-number(($yval_max),''00.00'')"/></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:otherwise>
                 <line x1="{($margin_left)+($bar_width*(position()-1))}" y1="{($graph_height)-($margin_bottom)+3}" x2="{($margin_left)+($bar_width*(position()-1))}" y2="{($graph_height)-($margin_bottom)+0}" style="stroke:lightblue;stroke-width:1" /> 
               </xsl:otherwise>
             </xsl:choose>    
           </xsl:for-each>
           <xsl:variable name="v_path0">
             <xsl:for-each select="ROWSET/ROW/C_CONT0_CPU">
               <xsl:variable name="x_val0">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val0">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val0,'','',$y_val0,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path0} {$x_val0},{($graph_height)-($margin_bottom)} {$margin_left},{($graph_height)-($margin_bottom)}" style="fill:aquamarine;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path1">
             <xsl:for-each select="ROWSET/ROW/C_CONT0_WAIT">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val1">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val1">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val1,'','',$y_val1,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path0}{$v_path1}" style="fill:steelblue;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path2">
             <xsl:for-each select="ROWSET/ROW/C_CONT1_CPU">
               <xsl:variable name="x_val2">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val2">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val2,'','',$y_val2,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path1}{$v_path2}" style="fill:darkkhaki;stroke:none;stroke-width:1" />'
           )
    ||
    TO_CLOB(
          '<xsl:variable name="v_path3">
             <xsl:for-each select="ROWSET/ROW/C_CONT1_WAIT">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val3">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val3">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val3,'','',$y_val3,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path2}{$v_path3}" style="fill:gold;stroke:none;stroke-width:1" />'
           )
    ||
    TO_CLOB(
          '<xsl:variable name="v_path4">
             <xsl:for-each select="ROWSET/ROW/C_CONT2_CPU">
               <xsl:variable name="x_val4">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val4">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val4,'','',$y_val4,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path3}{$v_path4}" style="fill:lightsalmon;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path5">
             <xsl:for-each select="ROWSET/ROW/C_CONT2_WAIT">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val5">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val5">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val5,'','',$y_val5,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path4}{$v_path5}" style="fill:orangered;stroke:none;stroke-width:1" />'
           )
    ||
    TO_CLOB(
          '<xsl:variable name="v_path6">
             <xsl:for-each select="ROWSET/ROW/C_CONT3_CPU">
               <xsl:variable name="x_val6">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val6">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val6,'','',$y_val6,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path5}{$v_path6}" style="fill:plum;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path7">
             <xsl:for-each select="ROWSET/ROW/C_CONT3_WAIT">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val7">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val7">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val7,'','',$y_val7,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path6}{$v_path7}" style="fill:magenta;stroke:none;stroke-width:1" /><xsl:variable name="v_path8">
             <xsl:for-each select="ROWSET/ROW/C_CONT4_CPU">
               <xsl:variable name="x_val8">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val8">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val8,'','',$y_val8,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path7}{$v_path8}" style="fill:skyblue;stroke:none;stroke-width:1" />'
           )
    ||
    TO_CLOB(
          '<xsl:variable name="v_path9">
             <xsl:for-each select="ROWSET/ROW/C_CONT4_WAIT">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val9">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val9">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val9,'','',$y_val9,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path8}{$v_path9}" style="fill:dodgerblue;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path10">
             <xsl:for-each select="ROWSET/ROW/C_CONT5_CPU">
               <xsl:variable name="x_val10">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val10">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val10,'','',$y_val10,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path9}{$v_path10}" style="fill:greenyellow;stroke:none;stroke-width:1" />'
           )
    ||
    TO_CLOB(
          '<xsl:variable name="v_path11">
             <xsl:for-each select="ROWSET/ROW/C_CONT5_WAIT">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val11">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val11">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val11,'','',$y_val11,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path10}{$v_path11}" style="fill:limegreen;stroke:none;stroke-width:1" />
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+5}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">CDB Wide CPU</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+0}" width="{10}" height="{6}" fill="aquamarine" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+13}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">CDB Wide Wait</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+8}" width="{10}" height="{6}" fill="steelblue" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+21}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">CDB$ROOT CPU</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+16}" width="{10}" height="{6}" fill="darkkhaki" stroke="black"/>   
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+29}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">CDB$ROOT Wait</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+24}" width="{10}" height="{6}" fill="gold" stroke="black"/>   
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+37}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">PDB1 CPU</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+32}" width="{10}" height="{6}" fill="lightsalmon" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+45}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">PDB1 Wait</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+40}" width="{10}" height="{6}" fill="orangered" stroke="black"/>'
           ) 
    || 
    TO_CLOB(
          '<text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+53}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">PDB2 CPU</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+48}" width="{10}" height="{6}" fill="plum" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+61}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">PDB2 Wait</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+56}" width="{10}" height="{6}" fill="magenta" stroke="black"/>
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+69}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">PDB3 CPU</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+64}" width="{10}" height="{6}" fill="skyblue" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+77}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">PDB3 Wait</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+72}" width="{10}" height="{6}" fill="dodgerblue" stroke="black"/>
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+85}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">PDB4 CPU</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+80}" width="{10}" height="{6}" fill="greenyellow" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+93}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">PDB4 Wait</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+88}" width="{10}" height="{6}" fill="limegreen" stroke="black"/> 
           <xsl:choose>
             <xsl:when test="$yval_max&gt;$cpu_count">
               <line x1="{($margin_left)-5}" y1="{($graph_height)-($margin_bottom)-((($yval_min)-($cpu_count))*(100 div (($yval_min)-($yval_max))))}" x2="{($graph_width)-($margin_right)+5}" y2="{($graph_height)-($margin_bottom)-((($yval_min)-($cpu_count))*(100 div (($yval_min)-($yval_max))))}" style="stroke-dasharray: 9, 5;stroke:red;stroke-width:1" />
               <text x="{($margin_left)+2}" y="{($graph_height)-($margin_bottom)-((($yval_min)-($cpu_count))*(100 div (($yval_min)-($yval_max))))-2}" style="fill:red; stroke: none;font-size:8px;text-anchor=start">CPU cores</text>
             </xsl:when>
             <xsl:otherwise>
               <text x="{($margin_left)-38}" y="{($graph_height)-($margin_bottom)-93}" style="fill:red; stroke: none;font-size:6px;text-anchor=start"><xsl:value-of select="format-number((($yval_max) div ($cpu_count))*100,''00'')"/>% cpu cores</text>
             </xsl:otherwise>
           </xsl:choose>   
         </svg>
       </xsl:template>
     </xsl:stylesheet>'
           )
   )
   ) 
FROM dual;

SPOOL OFF
SET HEADING ON

SET VERIFY   ON
SET FEEDBACK ON

Result:

generate_svg_22h_21

Result with the query of part XXI on the same period:

generate_svg_21b

Remark:

  • The two queries have been executed from the CDB$ROOT container by the C##LSS common user,
  • The view v$cdb_pdb_aas_lss has been created from the CDB$ROOT container in the C##LSS schema,
  • We have excluded the PDB$SEED container (con_id=2) but if you want to focus on its activity it could be added in the selected containers.

Generating SVG graphics with SQL*Plus – Part XXI – Stacked area graph – Average Active Sessions – Light Sampling Sessions

Scope

In a previous post we have set up Light Sampling Sessions (LSS) and we would like to display the average active sessions for the last hour like in the part XX. The difference is that LSS is a sampling process meanwhile the view v$waitclassmetric_history is an accumulating statistics process. We will keep the sampling period interval to 5 seconds.

Instead of using directly the table lss$_sampling_session, we will create a view in order to display the average active sessions.

View creation – Step 1

Every minute we will count the number of active sessions that are linked to a wait class or a cpu state as follow:

SELECT TO_CHAR(sample_time,'YYYYMMDDHH24MI') sample_yyyymmddhhmi,
       MAX(sample_id) - MIN(sample_id) nb_samples,
       COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),-1,1)) count_cpu,
       COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),0,1))  count_other,
       COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),1,1))  count_application,
       COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),2,1))  count_configuration,
       COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),3,1))  count_administrative,
       COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),4,1))  count_concurrency,
       COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),5,1))  count_commit,
       COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),7,1))  count_network,
       COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),8,1))  count_user_io,
       COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),9,1))  count_system_io,
       COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),10,1)) count_scheduler,
       COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),11,1)) count_cluster,
       COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),12,1)) count_queueing
FROM lss$_sampling_session
GROUP BY TO_CHAR(sample_time,'YYYYMMDDHH24MI')

Remark:

  • The session state means ‘C’ for a CPU state and ‘W’ for a wait event state,
  • The CPU is linked to the virtual wait class -1.

View creation – Step 2

In the LSS sampling process, it might happen that a specific period of time does not contain any data e.g. LSS process is not working during this period.
We will handle the fact that the sampling process is inactive during the last hour as follow:

SELECT NVL(co_base_qry.sample_yyyymmddhhmi,time_window.start_time) sample_yyyymmddhhmi,
       NVL(co_base_qry.nb_samples,1)           nb_samples,
       NVL(co_base_qry.count_cpu,0)            count_cpu,
       NVL(co_base_qry.count_other,0)          count_other,
       NVL(co_base_qry.count_application,0)    count_application,
       NVL(co_base_qry.count_configuration,0)  count_configuration,
       NVL(co_base_qry.count_administrative,0) count_administrative,
       NVL(co_base_qry.count_concurrency,0)    count_concurrency,
       NVL(co_base_qry.count_commit,0)         count_commit,
       NVL(co_base_qry.count_network,0)        count_network,
       NVL(co_base_qry.count_user_io,0)        count_user_io,
       NVL(co_base_qry.count_system_io,0)      count_system_io,
       NVL(co_base_qry.count_scheduler,0)      count_scheduler,
       NVL(co_base_qry.count_cluster,0)        count_cluster,
       NVL(co_base_qry.count_queueing,0)       count_queueing
FROM
   (SELECT TO_CHAR(SYSDATE - (LEVEL/24/60),'YYYYMMDDHH24MI') start_time
    FROM DUAL 
    CONNECT BY LEVEL <= 61
    ) time_window
LEFT OUTER JOIN 
   (SELECT TO_CHAR(sample_time,'YYYYMMDDHH24MI') sample_yyyymmddhhmi,
           MAX(sample_id) - MIN(sample_id) nb_samples,
           COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),-1,1)) count_cpu,
           COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),0,1))  count_other,
           COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),1,1))  count_application,
           COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),2,1))  count_configuration,
           COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),3,1))  count_administrative,
           COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),4,1))  count_concurrency,
           COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),5,1))  count_commit,
           COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),7,1))  count_network,
           COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),8,1))  count_user_io,
           COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),9,1))  count_system_io,
           COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),10,1)) count_scheduler,
           COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),11,1)) count_cluster,
           COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),12,1)) count_queueing
    FROM lss$_sampling_session
    GROUP BY TO_CHAR(sample_time,'YYYYMMDDHH24MI')
    ) co_base_qry
  ON time_window.start_time=co_base_qry.sample_yyyymmddhhmi

View creation – Step 3

To define how many sessions in average are waiting on a wait class or are using cpu during a minute, we will count the wait class and the cpu states on a period of time of one minute and we will divide by the number of samples plus one as follow:

SELECT sample_yyyymmddhhmi,
       TRUNC((count_cpu/(nb_samples+1)),3)            aas1,  --aas_cpu,
       TRUNC((count_other/(nb_samples+1)),3)          aas2,  --aas_other,
       TRUNC((count_application/(nb_samples+1)),3)    aas3,  --aas_application,
       TRUNC((count_configuration/(nb_samples+1)),3)  aas4,  --aas_configuration,
       TRUNC((count_administrative/(nb_samples+1)),3) aas5,  --aas_administrative,
       TRUNC((count_concurrency/(nb_samples+1)),3)    aas6,  --aas_concurrency,
       TRUNC((count_commit/(nb_samples+1)),3)         aas7,  --aas_commit,
       TRUNC((count_network/(nb_samples+1)),3)        aas8,  --aas_network,
       TRUNC((count_user_io/(nb_samples+1)),3)        aas9,  --aas_user_io,
       TRUNC((count_system_io/(nb_samples+1)),3)      aas10, --aas_system_io,
       TRUNC((count_scheduler/(nb_samples+1)),3)      aas11, --aas_scheduler,
       TRUNC((count_cluster/(nb_samples+1)),3)        aas12, --aas_cluster,
       TRUNC((count_queueing/(nb_samples+1)),3)       aas13  --aas_queueing    
FROM 
   (SELECT NVL(co_base_qry.sample_yyyymmddhhmi,time_window.start_time) sample_yyyymmddhhmi,
           NVL(co_base_qry.nb_samples,1)           nb_samples,
           NVL(co_base_qry.count_cpu,0)            count_cpu,
           NVL(co_base_qry.count_other,0)          count_other,
           NVL(co_base_qry.count_application,0)    count_application,
           NVL(co_base_qry.count_configuration,0)  count_configuration,
           NVL(co_base_qry.count_administrative,0) count_administrative,
           NVL(co_base_qry.count_concurrency,0)    count_concurrency,
           NVL(co_base_qry.count_commit,0)         count_commit,
           NVL(co_base_qry.count_network,0)        count_network,
           NVL(co_base_qry.count_user_io,0)        count_user_io,
           NVL(co_base_qry.count_system_io,0)      count_system_io,
           NVL(co_base_qry.count_scheduler,0)      count_scheduler,
           NVL(co_base_qry.count_cluster,0)        count_cluster,
           NVL(co_base_qry.count_queueing,0)       count_queueing
    FROM
       (SELECT TO_CHAR(SYSDATE - (LEVEL/24/60),'YYYYMMDDHH24MI') start_time
        FROM DUAL 
        CONNECT BY LEVEL <= 61
        ) time_window
    LEFT OUTER JOIN 
       (SELECT TO_CHAR(sample_time,'YYYYMMDDHH24MI') sample_yyyymmddhhmi,
               MAX(sample_id) - MIN(sample_id) nb_samples,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),-1,1)) count_cpu,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),0,1))  count_other,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),1,1))  count_application,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),2,1))  count_configuration,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),3,1))  count_administrative,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),4,1))  count_concurrency,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),5,1))  count_commit,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),7,1))  count_network,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),8,1))  count_user_io,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),9,1))  count_system_io,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),10,1)) count_scheduler,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),11,1)) count_cluster,
               COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),12,1)) count_queueing
        FROM lss$_sampling_session
        GROUP BY TO_CHAR(sample_time,'YYYYMMDDHH24MI')
        ) co_base_qry
      ON time_window.start_time=co_base_qry.sample_yyyymmddhhmi
   )

At this stage we have a similar result than the one given by the view v$waitclassmetric_history except that we have already pivoted the AAS (Average Active Sessions) of the different wait class and cpu events.

View creation – Step 4

Finally we will accumulate the different wait class and cpu AAS values from the CPU to the QUEUEING wait class as follow:

CREATE OR REPLACE VIEW v$aas_light_sampling_sessions
AS
SELECT sample_yyyymmddhhmi,
       SUBSTR(sample_yyyymmddhhmi,9,2) || ':' || SUBSTR(sample_yyyymmddhhmi,11,2) BEGIN_TIME,
       aas1                                                                 C_CPU,
       aas1+aas2                                                            C_OTHER,
       aas1+aas2+aas3                                                       C_APPLICATION,
       aas1+aas2+aas3+aas4                                                  C_CONFIGURATION,
       aas1+aas2+aas3+aas4+aas5                                             C_ADMINISTRATIVE,
       aas1+aas2+aas3+aas4+aas5+aas6                                        C_CONCURRENCY,
       aas1+aas2+aas3+aas4+aas5+aas6+aas7                                   C_COMMIT,
       aas1+aas2+aas3+aas4+aas5+aas6+aas7+aas8                              C_NETWORK,
       aas1+aas2+aas3+aas4+aas5+aas6+aas7+aas8+aas9                         C_USER_IO,
       aas1+aas2+aas3+aas4+aas5+aas6+aas7+aas8+aas9+aas10                   C_SYSTEM_IO,
       aas1+aas2+aas3+aas4+aas5+aas6+aas7+aas8+aas9+aas10+aas11             C_SCHEDULER,
       aas1+aas2+aas3+aas4+aas5+aas6+aas7+aas8+aas9+aas10+aas11+aas12       C_CLUSTER,
       aas1+aas2+aas3+aas4+aas5+aas6+aas7+aas8+aas9+aas10+aas11+aas12+aas13 C_QUEUEING,
       MAX(CEIL(aas1+aas2+aas3+aas4+aas5+aas6+aas7+aas8+aas9+aas10+aas11+aas12+aas13)) OVER() MAX_AAS
FROM
   (SELECT sample_yyyymmddhhmi,
           TRUNC((count_cpu/(nb_samples+1)),3)            aas1,  --aas_cpu,
           TRUNC((count_other/(nb_samples+1)),3)          aas2,  --aas_other,
           TRUNC((count_application/(nb_samples+1)),3)    aas3,  --aas_application,
           TRUNC((count_configuration/(nb_samples+1)),3)  aas4,  --aas_configuration,
           TRUNC((count_administrative/(nb_samples+1)),3) aas5,  --aas_administrative,
           TRUNC((count_concurrency/(nb_samples+1)),3)    aas6,  --aas_concurrency,
           TRUNC((count_commit/(nb_samples+1)),3)         aas7,  --aas_commit,
           TRUNC((count_network/(nb_samples+1)),3)        aas8,  --aas_network,
           TRUNC((count_user_io/(nb_samples+1)),3)        aas9,  --aas_user_io,
           TRUNC((count_system_io/(nb_samples+1)),3)      aas10, --aas_system_io,
           TRUNC((count_scheduler/(nb_samples+1)),3)      aas11, --aas_scheduler,
           TRUNC((count_cluster/(nb_samples+1)),3)        aas12, --aas_cluster,
           TRUNC((count_queueing/(nb_samples+1)),3)       aas13  --aas_queueing    
    FROM 
       (SELECT NVL(co_base_qry.sample_yyyymmddhhmi,time_window.start_time) sample_yyyymmddhhmi,
               NVL(co_base_qry.nb_samples,1)           nb_samples,
               NVL(co_base_qry.count_cpu,0)            count_cpu,
               NVL(co_base_qry.count_other,0)          count_other,
               NVL(co_base_qry.count_application,0)    count_application,
               NVL(co_base_qry.count_configuration,0)  count_configuration,
               NVL(co_base_qry.count_administrative,0) count_administrative,
               NVL(co_base_qry.count_concurrency,0)    count_concurrency,
               NVL(co_base_qry.count_commit,0)         count_commit,
               NVL(co_base_qry.count_network,0)        count_network,
               NVL(co_base_qry.count_user_io,0)        count_user_io,
               NVL(co_base_qry.count_system_io,0)      count_system_io,
               NVL(co_base_qry.count_scheduler,0)      count_scheduler,
               NVL(co_base_qry.count_cluster,0)        count_cluster,
               NVL(co_base_qry.count_queueing,0)       count_queueing
        FROM
           (SELECT TO_CHAR(SYSDATE - (LEVEL/24/60),'YYYYMMDDHH24MI') start_time
            FROM DUAL 
            CONNECT BY LEVEL <= 61
            ) time_window
        LEFT OUTER JOIN 
           (SELECT TO_CHAR(sample_time,'YYYYMMDDHH24MI') sample_yyyymmddhhmi,
                   MAX(sample_id) - MIN(sample_id) nb_samples,
                   COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),-1,1)) count_cpu,
                   COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),0,1))  count_other,
                   COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),1,1))  count_application,
                   COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),2,1))  count_configuration,
                   COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),3,1))  count_administrative,
                   COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),4,1))  count_concurrency,
                   COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),5,1))  count_commit,
                   COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),7,1))  count_network,
                   COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),8,1))  count_user_io,
                   COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),9,1))  count_system_io,
                   COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),10,1)) count_scheduler,
                   COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),11,1)) count_cluster,
                   COUNT(DECODE(DECODE(session_state,'C',-1,wait_class#),12,1)) count_queueing
            FROM lss$_sampling_session
            GROUP BY TO_CHAR(sample_time,'YYYYMMDDHH24MI')
            ) co_base_qry
          ON time_window.start_time=co_base_qry.sample_yyyymmddhhmi
       )
  );

Modified source query

We will use the query defined in the part XX as a starting point. We will modify the source query as follow:

SELECT BEGIN_TIME,
       C_CPU,
       C_OTHER,
       C_APPLICATION,
       C_CONFIGURATION,
       C_ADMINISTRATIVE,
       C_CONCURRENCY,
       C_COMMIT,
       C_NETWORK,
       C_USER_IO,
       C_SYSTEM_IO,
       C_SCHEDULER,
       C_CLUSTER,
       C_QUEUEING ,
       MAX_AAS,
       (SELECT value FROM v$parameter WHERE name='cpu_count') CPU_COUNT
FROM v$aas_light_sampling_sessions
ORDER BY sample_yyyymmddhhmi

XSLT variables

  • The variable “graph_name” is set to ‘LSS Active Sessions – Waiting + Working’,
  • The variable “yval_max” is set to the first value of the column MAX_AAS,
  • The variable “bar_width” is set to ’10’,
  • The variable “graph_width” is set to ‘600+$margin_left+$margin_right’.

The X axis scale time has been modified by adding small vertical lines every minutes.

Modified query

SET LINESIZE      2000
SET LONGCHUNKSIZE 30000
SET LONG          30000

SET FEEDBACK OFF
SET VERIFY   OFF
SET PAGESIZE 0

SET HEADING OFF

SPOOL generate_svg_21b.svg

SELECT XMLTRANSFORM
   (DBMS_XMLGEN.GETXMLTYPE
      ('SELECT BEGIN_TIME,
               C_CPU,
               C_OTHER,
               C_APPLICATION,
               C_CONFIGURATION,
               C_ADMINISTRATIVE,
               C_CONCURRENCY,
               C_COMMIT,
               C_NETWORK,
               C_USER_IO,
               C_SYSTEM_IO,
               C_SCHEDULER,
               C_CLUSTER,
               C_QUEUEING ,
               MAX_AAS,
       (SELECT value FROM v$parameter WHERE name=''cpu_count'') CPU_COUNT
       FROM v$aas_light_sampling_sessions
       ORDER BY sample_yyyymmddhhmi')
,      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">10</xsl:variable>
     <xsl:variable name="graph_width"><xsl:value-of select="600+$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">LSS Active Sessions - Waiting + Working</xsl:variable>
     <xsl:variable name="graph_unit">Session Count</xsl:variable>
     <xsl:variable name="yval_max"><xsl:value-of select="/descendant::MAX_AAS[position()=1]"/></xsl:variable>
     <xsl:variable name="yval_min">0</xsl:variable>
     <xsl:variable name="cpu_count"><xsl:value-of select="/descendant::CPU_COUNT[position()=1]"/></xsl:variable>
       <xsl:template match="/">'
           )
    || 
    TO_CLOB(
         '<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)-24}" y="{($graph_height)-($margin_bottom)-2}"   style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="format-number(($yval_min),''00.00'')"/></text>
           <text x="{($margin_left)-24}" y="{($graph_height)-($margin_bottom)-25}"  style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="format-number((($yval_min)+(1*(($yval_max)-($yval_min)) div 4)),''00.00'')"/></text>
           <text x="{($margin_left)-24}" y="{($graph_height)-($margin_bottom)-50}"  style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="format-number((($yval_min)+((($yval_max)-($yval_min)) div 2)),''00.00'')"/></text>
           <text x="{($margin_left)-24}" y="{($graph_height)-($margin_bottom)-75}"  style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="format-number((($yval_min)+(3*(($yval_max)-($yval_min)) div 4)),''00.00'')"/></text>
           <text x="{($margin_left)-24}" y="{($graph_height)-($margin_bottom)-100}" style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="format-number(($yval_max),''00.00'')"/></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:otherwise>
                 <line x1="{($margin_left)+($bar_width*(position()-1))}" y1="{($graph_height)-($margin_bottom)+3}" x2="{($margin_left)+($bar_width*(position()-1))}" y2="{($graph_height)-($margin_bottom)+0}" style="stroke:lightblue;stroke-width:1" /> 
               </xsl:otherwise>
             </xsl:choose>    
           </xsl:for-each>
           <xsl:variable name="v_path0">
             <xsl:for-each select="ROWSET/ROW/C_CPU">
               <xsl:variable name="x_val0">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val0">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val0,'','',$y_val0,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path0} {$x_val0},{($graph_height)-($margin_bottom)} {$margin_left},{($graph_height)-($margin_bottom)}" style="fill:limegreen;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path1">
             <xsl:for-each select="ROWSET/ROW/C_OTHER">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val1">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val1">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val1,'','',$y_val1,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path0}{$v_path1}" style="fill:hotpink;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path2">
             <xsl:for-each select="ROWSET/ROW/C_APPLICATION">
               <xsl:variable name="x_val2">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val2">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val2,'','',$y_val2,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path1}{$v_path2}" style="fill:indianred;stroke:none;stroke-width:1" />'
           )
   ||
   TO_CLOB(
          '<xsl:variable name="v_path3">
             <xsl:for-each select="ROWSET/ROW/C_CONFIGURATION">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val3">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val3">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val3,'','',$y_val3,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path2}{$v_path3}" style="fill:olive;stroke:none;stroke-width:1" />'
           )
   ||
   TO_CLOB(
          '<xsl:variable name="v_path4">
             <xsl:for-each select="ROWSET/ROW/C_ADMINISTRATIVE">
               <xsl:variable name="x_val4">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val4">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val4,'','',$y_val4,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path3}{$v_path4}" style="fill:gray;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path5">
             <xsl:for-each select="ROWSET/ROW/C_CONCURRENCY">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val5">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val5">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val5,'','',$y_val5,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path4}{$v_path5}" style="fill:sienna;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path6">
             <xsl:for-each select="ROWSET/ROW/C_COMMIT">
               <xsl:variable name="x_val6">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val6">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val6,'','',$y_val6,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path5}{$v_path6}" style="fill:orange;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path7">
             <xsl:for-each select="ROWSET/ROW/C_NETWORK">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val7">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val7">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val7,'','',$y_val7,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path6}{$v_path7}" style="fill:tan;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path8">
             <xsl:for-each select="ROWSET/ROW/C_USER_IO">
               <xsl:variable name="x_val8">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val8">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val8,'','',$y_val8,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path7}{$v_path8}" style="fill:royalblue;stroke:none;stroke-width:1" />'
           )
   ||
   TO_CLOB(
          '<xsl:variable name="v_path9">
             <xsl:for-each select="ROWSET/ROW/C_SYSTEM_IO">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val9">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val9">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val9,'','',$y_val9,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path8}{$v_path9}" style="fill:skyblue;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path10">
             <xsl:for-each select="ROWSET/ROW/C_SCHEDULER">
               <xsl:variable name="x_val10">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val10">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val10,'','',$y_val10,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path9}{$v_path10}" style="fill:lightcyan;stroke:none;stroke-width:1" />'
           )
   ||
   TO_CLOB(
          '<xsl:variable name="v_path11">
             <xsl:for-each select="ROWSET/ROW/C_CLUSTER">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val11">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val11">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val11,'','',$y_val11,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path10}{$v_path11}" style="fill:lightgray;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path12">
             <xsl:for-each select="ROWSET/ROW/C_QUEUEING">
               <xsl:variable name="x_val12">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val12">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val12,'','',$y_val12,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path11}{$v_path12}" style="fill:bisque;stroke:none;stroke-width:1" />
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+5}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">CPU</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+0}" width="{10}" height="{6}" fill="limegreen" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+13}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">Other</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+8}" width="{10}" height="{6}" fill="hotpink" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+21}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">Application</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+16}" width="{10}" height="{6}" fill="indianred" stroke="black"/>   
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+29}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">Configuration</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+24}" width="{10}" height="{6}" fill="olive" stroke="black"/>   
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+37}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">Administrative</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+32}" width="{10}" height="{6}" fill="gray" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+45}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">Concurrency</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+40}" width="{10}" height="{6}" fill="sienna" stroke="black"/>'
           ) 
    || 
    TO_CLOB(
          '<text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+53}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">Commit</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+48}" width="{10}" height="{6}" fill="orange" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+61}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">Network</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+56}" width="{10}" height="{6}" fill="tan" stroke="black"/>  
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+69}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">User IO</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+64}" width="{10}" height="{6}" fill="royalblue" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+77}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">System IO</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+72}" width="{10}" height="{6}" fill="skyblue" stroke="black"/>
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+85}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">Scheduler</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+80}" width="{10}" height="{6}" fill="lightcyan" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+93}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">Cluster</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+88}" width="{10}" height="{6}" fill="lightgray" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+101}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">Queueing</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+96}" width="{10}" height="{6}" fill="bisque" stroke="black"/> 
           <xsl:choose>
             <xsl:when test="$yval_max&gt;$cpu_count">
               <line x1="{($margin_left)-5}" y1="{($graph_height)-($margin_bottom)-((($yval_min)-($cpu_count))*(100 div (($yval_min)-($yval_max))))}" x2="{($graph_width)-($margin_right)+5}" y2="{($graph_height)-($margin_bottom)-((($yval_min)-($cpu_count))*(100 div (($yval_min)-($yval_max))))}" style="stroke-dasharray: 9, 5;stroke:red;stroke-width:1" />
               <text x="{($margin_left)+2}" y="{($graph_height)-($margin_bottom)-((($yval_min)-($cpu_count))*(100 div (($yval_min)-($yval_max))))-2}" style="fill:red; stroke: none;font-size:8px;text-anchor=start">CPU cores</text>
             </xsl:when>
             <xsl:otherwise>
               <text x="{($margin_left)-38}" y="{($graph_height)-($margin_bottom)-93}" style="fill:red; stroke: none;font-size:6px;text-anchor=start"><xsl:value-of select="format-number((($yval_max) div ($cpu_count))*100,''00'')"/>% cpu cores</text>
             </xsl:otherwise>
           </xsl:choose>   
         </svg>
       </xsl:template>
     </xsl:stylesheet>'
           )
   )
   ) 
FROM dual;

SPOOL OFF
SET HEADING ON

SET VERIFY   ON
SET FEEDBACK ON

Result:

generate_svg_21b

Result with the query of part XX with “bar_width” set to ’10’ and “graph_width” set to ‘600+$margin_left+$margin_right’ for approximately the same period:

generate_svg_21b_20f_evo

Remarks:

  • The two queries have been executed from the CDB$ROOT container by the C##LSS common user,
  • The procedure DBMS_SAMPLING_SESSION.start_sampling has been also executed from the CDB$ROOT container by the C##LSS common user,
  • The view v$aas_light_sampling_sessions has been created from the CDB$ROOT container in the C##LSS schema,
  • The time period of the two previous graphs are not the same because the view v$waitclassmetric_history is not refreshed exactly every minute,
  • The graph shapes are not exactly the same but they look alike.

Generating SVG graphics with SQL*Plus – Part XX – Stacked area graph – Average Active Sessions – Waiting + Working

Flashback

The previous graph described in the part XIX displays the average active sessions linked to a wait class. This concerns the foreground sessions as well as the background sessions. If you would like to display only the foreground sessions you should replace average_waiter_count by time_waited_fg/intsize_csec, and if you would like to display only the background sessions you should replace average_waiter_count by (time_waited-time_waited_fg)/intsize_csec.
The column time_waited_fg has been introduced in the Oracle 11g release.

Working part

The working part is linked to the CPU time. If you want to know the different kinds of CPU time I suggest you to consult an article of Kyle Hailey which can be found at http://datavirtualizer.com/oracle-cpu-time/ .
In our case we will only add only the “CPU used”. This value can be found in the view v$sysmetric_history for the metric_id=2075 ‘CPU Usage Per Sec’ and the group_id=2 and must be divided by 100 in order to be transformed as an average session count unit. We will modify the source query as follow:

SELECT TO_CHAR(begin_time,'HH24:MI') BEGIN_TIME
,      c_cpu            C_CPU
,      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(CEIL(c_queueing)) OVER() MAX_AVERAGE_WAITER_COUNT
,      (SELECT value FROM v$parameter WHERE name='cpu_count') CPU_COUNT
FROM (
   SELECT * 
   FROM (
      SELECT begin_time
      ,      wait_class#
      ,      SUM(average_waiter_count) OVER (PARTITION BY begin_time ORDER BY wait_class#) average_waiter_count_acc
      FROM (
         SELECT begin_time,
                wait_class#,
                average_waiter_count 
         FROM v$waitclassmetric_history
         WHERE wait_class# <> 6
        UNION
         SELECT begin_time
         ,      -1 wait_class#
         ,      value/100 average_waiter_count 
         FROM v$sysmetric_history 
         WHERE metric_id = 2075
           AND group_id = 2
           )
        ) tb 
   PIVOT (
      MAX(average_waiter_count_acc) 
      FOR wait_class# IN (-1 as c_cpu,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

We have slightly modified the previous query by adding the CPU as the wait_class#=-1. We have also added the number of CPU cores linked to the parameter ‘cpu_count’. We will display this parameter as a red dashed line on the graph.

XSLT variables

We will add one additional variable in the XSLT document:

  • <xsl:variable name="cpu_count"><xsl:value-of select="/descendant::CPU_COUNT[position()=1]"/></xsl:variable>

    Number of CPU cores.

Furthermore:

  • The variable “graph_name” is set to ‘Active Sessions – Waiting + Working’.

XSLT processing

The modifications are the following:

  • The variable “v_path12” has been added and is linked to the column C_QUEUEING,
  • There has been a shift between the variables “v_pathN” and the columns “C_M” e.g. the variable “v_path0” is now linked to the column C_CPU, … the variable “v_path11” is now linked to the column C_CLUSTER,
  • A red dashed line indicating the number of CPU cores will be displayed if the number of average sessions is greater than the number of CPU Cores, otherwise a text under the maximum Y-axis label will be displayed indicating the percentage of CPU cores.

Modified query

You will find below the modified query:

SET LINESIZE      1000
SET LONGCHUNKSIZE 30000
SET LONG          30000

SET FEEDBACK OFF
SET VERIFY   OFF
SET PAGESIZE 0

SET HEADING OFF

SPOOL generate_svg_20f.svg

SELECT XMLTRANSFORM
   (DBMS_XMLGEN.GETXMLTYPE
      ('SELECT TO_CHAR(begin_time,''HH24:MI'') BEGIN_TIME
        ,      c_cpu            C_CPU
        ,      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(CEIL(c_queueing)) OVER() MAX_AVERAGE_WAITER_COUNT
        ,      (SELECT value FROM v$parameter WHERE name=''cpu_count'') CPU_COUNT
        FROM (
           SELECT * 
           FROM (
              SELECT begin_time
              ,      wait_class#
              ,      SUM(average_waiter_count) OVER (PARTITION BY begin_time ORDER BY wait_class#) average_waiter_count_acc
              FROM (
                 SELECT begin_time,
                        wait_class#,
                        average_waiter_count 
                 FROM v$waitclassmetric_history
                 WHERE wait_class# <> 6
                UNION
                 SELECT begin_time
                 ,      -1 wait_class#
                 ,      value/100 average_waiter_count 
                 FROM v$sysmetric_history 
                 WHERE metric_id = 2075
                   AND group_id = 2
                   )
                ) tb 
           PIVOT (
              MAX(average_waiter_count_acc) 
              FOR wait_class# IN (-1 as c_cpu,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="300+$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">Active Sessions - Waiting + Working</xsl:variable>
     <xsl:variable name="graph_unit">Session Count</xsl:variable>
     <xsl:variable name="yval_max"><xsl:value-of select="/descendant::MAX_AVERAGE_WAITER_COUNT[position()=1]"/></xsl:variable>
     <xsl:variable name="yval_min">0</xsl:variable>
     <xsl:variable name="cpu_count"><xsl:value-of select="/descendant::CPU_COUNT[position()=1]"/></xsl:variable>
       <xsl:template match="/">'
           )
    || 
    TO_CLOB(
         '<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)-24}" y="{($graph_height)-($margin_bottom)-2}"   style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="format-number(($yval_min),''00.00'')"/></text>
           <text x="{($margin_left)-24}" y="{($graph_height)-($margin_bottom)-25}"  style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="format-number((($yval_min)+(1*(($yval_max)-($yval_min)) div 4)),''00.00'')"/></text>
           <text x="{($margin_left)-24}" y="{($graph_height)-($margin_bottom)-50}"  style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="format-number((($yval_min)+((($yval_max)-($yval_min)) div 2)),''00.00'')"/></text>
           <text x="{($margin_left)-24}" y="{($graph_height)-($margin_bottom)-75}"  style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="format-number((($yval_min)+(3*(($yval_max)-($yval_min)) div 4)),''00.00'')"/></text>
           <text x="{($margin_left)-24}" y="{($graph_height)-($margin_bottom)-100}" style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="format-number(($yval_max),''00.00'')"/></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:variable name="v_path0">
             <xsl:for-each select="ROWSET/ROW/C_CPU">
               <xsl:variable name="x_val0">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val0">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val0,'','',$y_val0,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path0} {$x_val0},{($graph_height)-($margin_bottom)} {$margin_left},{($graph_height)-($margin_bottom)}" style="fill:lightgreen;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path1">
             <xsl:for-each select="ROWSET/ROW/C_OTHER">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val1">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val1">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val1,'','',$y_val1,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path0}{$v_path1}" style="fill:hotpink;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path2">
             <xsl:for-each select="ROWSET/ROW/C_APPLICATION">
               <xsl:variable name="x_val2">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val2">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val2,'','',$y_val2,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path1}{$v_path2}" style="fill:indianred;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path3">
             <xsl:for-each select="ROWSET/ROW/C_CONFIGURATION">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val3">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val3">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val3,'','',$y_val3,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path2}{$v_path3}" style="fill:olive;stroke:none;stroke-width:1" />'
           )
   ||
   TO_CLOB(
          '<xsl:variable name="v_path4">
             <xsl:for-each select="ROWSET/ROW/C_ADMINISTRATIVE">
               <xsl:variable name="x_val4">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val4">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val4,'','',$y_val4,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path3}{$v_path4}" style="fill:gray;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path5">
             <xsl:for-each select="ROWSET/ROW/C_CONCURRENCY">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val5">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val5">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val5,'','',$y_val5,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path4}{$v_path5}" style="fill:sienna;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path6">
             <xsl:for-each select="ROWSET/ROW/C_COMMIT">
               <xsl:variable name="x_val6">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val6">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val6,'','',$y_val6,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path5}{$v_path6}" style="fill:orange;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path7">
             <xsl:for-each select="ROWSET/ROW/C_NETWORK">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val7">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val7">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val7,'','',$y_val7,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path6}{$v_path7}" style="fill:tan;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path8">
             <xsl:for-each select="ROWSET/ROW/C_USER_IO">
               <xsl:variable name="x_val8">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val8">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val8,'','',$y_val8,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path7}{$v_path8}" style="fill:royalblue;stroke:none;stroke-width:1" />'
           )
   ||
   TO_CLOB(
          '<xsl:variable name="v_path9">
             <xsl:for-each select="ROWSET/ROW/C_SYSTEM_IO">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val9">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val9">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val9,'','',$y_val9,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path8}{$v_path9}" style="fill:skyblue;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path10">
             <xsl:for-each select="ROWSET/ROW/C_SCHEDULER">
               <xsl:variable name="x_val10">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val10">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val10,'','',$y_val10,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path9}{$v_path10}" style="fill:lightcyan;stroke:none;stroke-width:1" />'
           )
   ||
   TO_CLOB(
          '<xsl:variable name="v_path11">
             <xsl:for-each select="ROWSET/ROW/C_CLUSTER">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val11">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val11">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val11,'','',$y_val11,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path10}{$v_path11}" style="fill:lightgray;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path12">
             <xsl:for-each select="ROWSET/ROW/C_QUEUEING">
               <xsl:variable name="x_val12">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val12">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val12,'','',$y_val12,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path11}{$v_path12}" style="fill:bisque;stroke:none;stroke-width:1" />
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+5}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">CPU used</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+0}" width="{10}" height="{6}" fill="lightgreen" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+13}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">Other</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+8}" width="{10}" height="{6}" fill="hotpink" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+21}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">Application</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+16}" width="{10}" height="{6}" fill="indianred" stroke="black"/>   
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+29}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">Configuration</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+24}" width="{10}" height="{6}" fill="olive" stroke="black"/>   
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+37}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">Administrative</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+32}" width="{10}" height="{6}" fill="gray" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+45}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">Concurrency</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+40}" width="{10}" height="{6}" fill="sienna" stroke="black"/>'
           ) 
    || 
    TO_CLOB(
          '<text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+53}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">Commit</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+48}" width="{10}" height="{6}" fill="orange" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+61}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">Network</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+56}" width="{10}" height="{6}" fill="tan" stroke="black"/>  
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+69}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">User IO</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+64}" width="{10}" height="{6}" fill="royalblue" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+77}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">System IO</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+72}" width="{10}" height="{6}" fill="skyblue" stroke="black"/>
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+85}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">Scheduler</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+80}" width="{10}" height="{6}" fill="lightcyan" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+93}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">Cluster</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+88}" width="{10}" height="{6}" fill="lightgray" stroke="black"/> 
           <text x="{($graph_width)-($margin_right)+33}" y="{($margin_top)+101}" style="fill:#000000; stroke: none;font-size:8px;text-anchor=start">Queueing</text>
           <rect x="{($graph_width)-($margin_right)+20}" y="{($margin_top)+96}" width="{10}" height="{6}" fill="bisque" stroke="black"/> 
           <xsl:choose>
             <xsl:when test="$yval_max&gt;$cpu_count">
               <line x1="{($margin_left)-5}" y1="{($graph_height)-($margin_bottom)-((($yval_min)-($cpu_count))*(100 div (($yval_min)-($yval_max))))}" x2="{($graph_width)-($margin_right)+5}" y2="{($graph_height)-($margin_bottom)-((($yval_min)-($cpu_count))*(100 div (($yval_min)-($yval_max))))}" style="stroke-dasharray: 9, 5;stroke:red;stroke-width:1" />
               <text x="{($margin_left)+2}" y="{($graph_height)-($margin_bottom)-((($yval_min)-($cpu_count))*(100 div (($yval_min)-($yval_max))))-2}" style="fill:red; stroke: none;font-size:8px;text-anchor=start">CPU cores</text>
             </xsl:when>
             <xsl:otherwise>
               <text x="{($margin_left)-38}" y="{($graph_height)-($margin_bottom)-93}" style="fill:red; stroke: none;font-size:6px;text-anchor=start"><xsl:value-of select="format-number((($yval_max) div ($cpu_count))*100,''00'')"/>% cpu cores</text>
             </xsl:otherwise>
           </xsl:choose>   
         </svg>
       </xsl:template>
     </xsl:stylesheet>'
           )
   )
   ) 
FROM dual;

SPOOL OFF
SET HEADING ON

SET VERIFY   ON
SET FEEDBACK ON

Result:

generate_svg_20f

Remarks:

  • Due to the use of the special character & in the XSLT processing you might type SET DEFINE OFF before executing this query,
  • Concerning the number of CPU cores and depending on the Oracle database edition and platform, a more accurate information can be found in the column cpu_core_count_current of the view v$license.

Generating SVG graphics with SQL*Plus – Part XIX – Stacked area graph – Average Active Sessions – Waiting

Average Active Sessions

The graph described in the part XVIII gives an indication about the “time waited” linked to the wait classes. However it could be interesting to know how many sessions in average are waiting on such or such wait class. This indication is given by the column “average_waiter_count” of the view v$waitclassmetric_history.

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() MAX_AVERAGE_WAITER_COUNT
FROM (
   SELECT * 
   FROM (
      SELECT begin_time
      ,      wait_class#
      ,      SUM(average_waiter_count) OVER (PARTITION BY begin_time ORDER BY wait_class#) average_waiter_count_acc
      FROM v$waitclassmetric_history
      WHERE wait_class# <> 6
        ) tb 
   PIVOT (
      MAX(average_waiter_count_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

XSLT variables

  • The variable “graph_name” is set to ‘Active Sessions – Waiting’,
  • The variable “graph_unit” is set to ‘Session Count’,
  • The variable “yval_max” is set to the first value of the column MAX_AVERAGE_WAITER_COUNT.

The values displayed on the y-axis are formatted with the function “format-number”.

Modified query

You will find below the modified query:

SET LINESIZE      1000
SET LONGCHUNKSIZE 30000
SET LONG          30000

SET FEEDBACK OFF
SET VERIFY   OFF
SET PAGESIZE 0

SET HEADING OFF

SPOOL generate_svg_19c.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() MAX_AVERAGE_WAITER_COUNT
        FROM (
           SELECT * 
           FROM (
              SELECT begin_time
              ,      wait_class#
              ,      SUM(average_waiter_count) OVER (PARTITION BY begin_time ORDER BY wait_class#) average_waiter_count_acc
              FROM v$waitclassmetric_history
              WHERE wait_class# <> 6
                ) tb 
           PIVOT (
              MAX(average_waiter_count_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="300+$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">Active Sessions - Waiting</xsl:variable>
     <xsl:variable name="graph_unit">Session Count</xsl:variable>
     <xsl:variable name="yval_max"><xsl:value-of select="/descendant::MAX_AVERAGE_WAITER_COUNT[position()=1]"/></xsl:variable>
     <xsl:variable name="yval_min">0</xsl:variable>
       <xsl:template match="/">'
           )
    || 
    TO_CLOB(
         '<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)-24}" y="{($graph_height)-($margin_bottom)-2}"   style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="format-number(($yval_min),''00.00'')"/></text>
           <text x="{($margin_left)-24}" y="{($graph_height)-($margin_bottom)-25}"  style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="format-number((($yval_min)+(1*(($yval_max)-($yval_min)) div 4)),''00.00'')"/></text>
           <text x="{($margin_left)-24}" y="{($graph_height)-($margin_bottom)-50}"  style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="format-number((($yval_min)+((($yval_max)-($yval_min)) div 2)),''00.00'')"/></text>
           <text x="{($margin_left)-24}" y="{($graph_height)-($margin_bottom)-75}"  style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="format-number((($yval_min)+(3*(($yval_max)-($yval_min)) div 4)),''00.00'')"/></text>
           <text x="{($margin_left)-24}" y="{($graph_height)-($margin_bottom)-100}" style="fill: #000000; stroke: none;font-size:8px;text-anchor=start"><xsl:value-of select="format-number(($yval_max),''00.00'')"/></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:variable name="v_path0">
             <xsl:for-each select="ROWSET/ROW/C_OTHER">
               <xsl:variable name="x_val0">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val0">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val0,'','',$y_val0,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path0} {$x_val0},{($graph_height)-($margin_bottom)} {$margin_left},{($graph_height)-($margin_bottom)}" style="fill:hotpink;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path1">
             <xsl:for-each select="ROWSET/ROW/C_APPLICATION">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val1">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val1">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val1,'','',$y_val1,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path0}{$v_path1}" style="fill:indianred;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path2">
             <xsl:for-each select="ROWSET/ROW/C_CONFIGURATION">
               <xsl:variable name="x_val2">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val2">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val2,'','',$y_val2,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path1}{$v_path2}" style="fill:olive;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path3">
             <xsl:for-each select="ROWSET/ROW/C_ADMINISTRATIVE">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val3">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val3">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val3,'','',$y_val3,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path2}{$v_path3}" style="fill:gray;stroke:none;stroke-width:1" />'
           )
   ||
   TO_CLOB(
          '<xsl:variable name="v_path4">
             <xsl:for-each select="ROWSET/ROW/C_CONCURRENCY">
               <xsl:variable name="x_val4">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val4">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val4,'','',$y_val4,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path3}{$v_path4}" style="fill:sienna;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path5">
             <xsl:for-each select="ROWSET/ROW/C_COMMIT">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val5">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val5">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val5,'','',$y_val5,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path4}{$v_path5}" style="fill:orange;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path6">
             <xsl:for-each select="ROWSET/ROW/C_NETWORK">
               <xsl:variable name="x_val6">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val6">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val6,'','',$y_val6,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path5}{$v_path6}" style="fill:tan;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path7">
             <xsl:for-each select="ROWSET/ROW/C_USER_IO">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val7">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val7">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val7,'','',$y_val7,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path6}{$v_path7}" style="fill:royalblue;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path8">
             <xsl:for-each select="ROWSET/ROW/C_SYSTEM_IO">
               <xsl:variable name="x_val8">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val8">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val8,'','',$y_val8,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path7}{$v_path8}" style="fill:skyblue;stroke:none;stroke-width:1" />'
           )
   ||
   TO_CLOB(
          '<xsl:variable name="v_path9">
             <xsl:for-each select="ROWSET/ROW/C_SCHEDULER">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val9">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val9">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val9,'','',$y_val9,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path8}{$v_path9}" style="fill:lightcyan;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path10">
             <xsl:for-each select="ROWSET/ROW/C_CLUSTER">
               <xsl:variable name="x_val10">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val10">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val10,'','',$y_val10,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path9}{$v_path10}" style="fill:lightgray;stroke:none;stroke-width:1" />'
           )
   ||
   TO_CLOB(
          '<xsl:variable name="v_path11">
             <xsl:for-each select="ROWSET/ROW/C_QUEUEING">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val11">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val11">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val11,'','',$y_val11,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path10}{$v_path11}" style="fill:bisque;stroke:none;stroke-width:1" />
           <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_19c

Result with the query of part XVIII for the same period:

generate_svg_19c_18a

Remark:

  • The queries have been executed from a PDB.

Shortly

We will add the “Working” part for the average active sessions.

Generating SVG graphics with SQL*Plus – Part XVIII – Stacked area graph

Area

The lines graph described in the part XVII will be used as a border for the areas graph and we will see that the order of the points in a line graph is important. Let’s start with two lines graph as described in the figure below:

generate_svg_18_ex1

We have a red line graph whose points are displayed from wa1 to wa3. We have also a blue line graph whose points are displayed from wb1 to wb3. Suppose that we want to display all those points in the same line graph starting by the points {wa1,wa2,wa3} and ending by the points {wb1,wb2,wb3}. The result is shown in the following figure:

generate_svg_18_ex2

If we consider that this line graph is the border of a polygon {wa1,wa2,wa3,wb1,wb2,wb3} let’s see what happens if we fill the interior area in the figure below:

generate_svg_18_ex3

It’s not exactly the expected result. Now, let’s rearrange the points of the line graph as {wa1,wa2,wa3,wb3,wb2,wb1} (that is to say that the points of the second line graph have been rearranged in a reverse order) and let’s restart the previous operation:

generate_svg_18_ex4

This is now the expected result! In order to display this area graph we can use the polyline element or the polygon element. We will use the polygon element.

XSLT processing

We will modify the XSLT processing defined in the part XVII as follow:

A) For the line graph defined by the variable “v_pathN” where N=2*i and i > 0:

  • The “v_pathN” generation is the same,
  • The area is defined by the points “{$v_path(N-1)}{$v_pathN}” as follow:
    <polygon points="{$v_path(N-1)}{$v_pathN}" style="fill:olive;stroke:none;stroke-width:1" />

B) For the line graph defined by the variable “v_pathM” where M=2*i+1:

  • The “x_val” value is read in the reverse order:
    <xsl:sort select="position()" order="descending" data-type="number"/>

    and

    <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
  • The area is defined by the points “{$v_path(M-1)}{$v_pathM}” as follow:
  • <polygon points="{$v_path(M-1)}{$v_pathM}" style="fill:indianred;stroke:none;stroke-width:1" />

C) For the line graph defined by the variable “v_path0” there is a special processing because the first line graph is the y-axis line:

<polygon points="{$v_path0} {$x_val0},{($graph_height)-($margin_bottom)} {$margin_left},{($graph_height)-($margin_bottom)}" style="fill:hotpink;stroke:none;stroke-width:1" />

Modified query

You will find below the modified query:

SET LINESIZE      1000
SET LONGCHUNKSIZE 30000
SET LONG          30000

SET FEEDBACK OFF
SET VERIFY   OFF
SET PAGESIZE 0

SET HEADING OFF

SPOOL generate_svg_18a.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="300+$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="/">'
           )
    || 
    TO_CLOB(
         '<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:variable name="v_path0">
             <xsl:for-each select="ROWSET/ROW/C_OTHER">
               <xsl:variable name="x_val0">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val0">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val0,'','',$y_val0,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path0} {$x_val0},{($graph_height)-($margin_bottom)} {$margin_left},{($graph_height)-($margin_bottom)}" style="fill:hotpink;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path1">
             <xsl:for-each select="ROWSET/ROW/C_APPLICATION">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val1">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val1">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val1,'','',$y_val1,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path0}{$v_path1}" style="fill:indianred;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path2">
             <xsl:for-each select="ROWSET/ROW/C_CONFIGURATION">
               <xsl:variable name="x_val2">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val2">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val2,'','',$y_val2,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path1}{$v_path2}" style="fill:olive;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path3">
             <xsl:for-each select="ROWSET/ROW/C_ADMINISTRATIVE">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val3">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val3">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val3,'','',$y_val3,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path2}{$v_path3}" style="fill:gray;stroke:none;stroke-width:1" />'
           )
   ||
   TO_CLOB(
          '<xsl:variable name="v_path4">
             <xsl:for-each select="ROWSET/ROW/C_CONCURRENCY">
               <xsl:variable name="x_val4">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val4">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val4,'','',$y_val4,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path3}{$v_path4}" style="fill:sienna;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path5">
             <xsl:for-each select="ROWSET/ROW/C_COMMIT">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val5">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val5">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val5,'','',$y_val5,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path4}{$v_path5}" style="fill:orange;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path6">
             <xsl:for-each select="ROWSET/ROW/C_NETWORK">
               <xsl:variable name="x_val6">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val6">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val6,'','',$y_val6,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path5}{$v_path6}" style="fill:tan;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path7">
             <xsl:for-each select="ROWSET/ROW/C_USER_IO">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val7">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val7">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val7,'','',$y_val7,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path6}{$v_path7}" style="fill:royalblue;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path8">
             <xsl:for-each select="ROWSET/ROW/C_SYSTEM_IO">
               <xsl:variable name="x_val8">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val8">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val8,'','',$y_val8,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path7}{$v_path8}" style="fill:skyblue;stroke:none;stroke-width:1" />'
           )
   ||
   TO_CLOB(
          '<xsl:variable name="v_path9">
             <xsl:for-each select="ROWSET/ROW/C_SCHEDULER">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val9">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val9">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val9,'','',$y_val9,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path8}{$v_path9}" style="fill:lightcyan;stroke:none;stroke-width:1" />
           <xsl:variable name="v_path10">
             <xsl:for-each select="ROWSET/ROW/C_CLUSTER">
               <xsl:variable name="x_val10">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val10">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val10,'','',$y_val10,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path9}{$v_path10}" style="fill:lightgray;stroke:none;stroke-width:1" />'
           )
   ||
   TO_CLOB(
          '<xsl:variable name="v_path11">
             <xsl:for-each select="ROWSET/ROW/C_QUEUEING">
               <xsl:sort select="position()" order="descending" data-type="number"/>
               <xsl:variable name="x_val11">
                 <xsl:value-of select="$margin_left+$bar_width*(last()-position())"/>
               </xsl:variable>
               <xsl:variable name="y_val11">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val11,'','',$y_val11,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polygon points="{$v_path10}{$v_path11}" style="fill:bisque;stroke:none;stroke-width:1" />
           <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_18a

Generating SVG graphics with SQL*Plus – Part XVII – Stacked area graph

Scope

The vertical stacked bar graph described in the part XVI can be useful, nevertheless we can also display the same data with a “smoother” graph. Instead of having a rectangle area at each event time, we could have a stacked area for each wait class for all the duration of the graph. We will achieve this in 2 steps:

  • In the first step we will display each wait class as a line graph,
  • In the second step we will display each wait class as a stacked area graph.

Line graph

We will use the query defined in the part IX as a starting point. We will modify the source query like in the part XVI 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

XSLT variables

  • The variable “graph_name1” is renamed to “graph_name” and is set to ‘Wait Classes’,
  • The variable “graph_unit1” is renamed to “graph_unit” and is set to ‘Time waited (in microseconds)’,
  • The variable “graph_name2” is deleted,
  • The variable “graph_unit2” is deleted,
  • The variable “yval1_min” is renamed to “yval_min” and is set to 0,
  • The variable “yval1_max” is renamed to “yval_max” and is set to the first value of the column SUM_TIME_WAITED,
  • The variable “yval2_min” is deleted,
  • The variable “yval2_max” is deleted,
  • The variable “margin_right” is set to 100.

Modified query

You will find below the modified query:

SET LINESIZE      1000
SET LONGCHUNKSIZE 30000
SET LONG          30000

SET FEEDBACK OFF
SET VERIFY   OFF
SET PAGESIZE 0

SET HEADING OFF

SPOOL generate_svg_17b.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="300+$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="/">'
           )
    || 
    TO_CLOB(
         '<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:variable name="v_path0">
             <xsl:for-each select="ROWSET/ROW/C_OTHER">
               <xsl:variable name="x_val0">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val0">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val0,'','',$y_val0,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polyline points="{$v_path0}" style="fill:none;stroke:hotpink;stroke-width:1" />
           <xsl:variable name="v_path1">
             <xsl:for-each select="ROWSET/ROW/C_APPLICATION">
               <xsl:variable name="x_val1">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val1">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val1,'','',$y_val1,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polyline points="{$v_path1}" style="fill:none;stroke:indianred;stroke-width:1" />
           <xsl:variable name="v_path2">
             <xsl:for-each select="ROWSET/ROW/C_CONFIGURATION">
               <xsl:variable name="x_val2">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val2">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val2,'','',$y_val2,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polyline points="{$v_path2}" style="fill:none;stroke:olive;stroke-width:1" />
           <xsl:variable name="v_path3">
             <xsl:for-each select="ROWSET/ROW/C_ADMINISTRATIVE">
               <xsl:variable name="x_val3">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val3">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val3,'','',$y_val3,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polyline points="{$v_path3}" style="fill:none;stroke:gray;stroke-width:1" />'
           )
   ||
   TO_CLOB(
          '<xsl:variable name="v_path4">
             <xsl:for-each select="ROWSET/ROW/C_CONCURRENCY">
               <xsl:variable name="x_val4">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val4">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val4,'','',$y_val4,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polyline points="{$v_path4}" style="fill:none;stroke:sienna;stroke-width:1" />
           <xsl:variable name="v_path5">
             <xsl:for-each select="ROWSET/ROW/C_COMMIT">
               <xsl:variable name="x_val5">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val5">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val5,'','',$y_val5,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polyline points="{$v_path5}" style="fill:none;stroke:orange;stroke-width:1" />
           <xsl:variable name="v_path6">
             <xsl:for-each select="ROWSET/ROW/C_NETWORK">
               <xsl:variable name="x_val6">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val6">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val6,'','',$y_val6,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polyline points="{$v_path6}" style="fill:none;stroke:tan;stroke-width:1" />
           <xsl:variable name="v_path7">
             <xsl:for-each select="ROWSET/ROW/C_USER_IO">
               <xsl:variable name="x_val7">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val7">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val7,'','',$y_val7,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polyline points="{$v_path7}" style="fill:none;stroke:royalblue;stroke-width:1" />
           <xsl:variable name="v_path8">
             <xsl:for-each select="ROWSET/ROW/C_SYSTEM_IO">
               <xsl:variable name="x_val8">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val8">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val8,'','',$y_val8,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polyline points="{$v_path8}" style="fill:none;stroke:skyblue;stroke-width:1" />'
           )
   ||
   TO_CLOB(
          '<xsl:variable name="v_path9">
             <xsl:for-each select="ROWSET/ROW/C_SCHEDULER">
               <xsl:variable name="x_val9">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val9">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val9,'','',$y_val9,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polyline points="{$v_path9}" style="fill:none;stroke:lightcyan;stroke-width:1" />
           <xsl:variable name="v_path10">
             <xsl:for-each select="ROWSET/ROW/C_CLUSTER">
               <xsl:variable name="x_val10">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val10">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val10,'','',$y_val10,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polyline points="{$v_path10}" style="fill:none;stroke:lightgray;stroke-width:1" />
           <xsl:variable name="v_path11">
             <xsl:for-each select="ROWSET/ROW/C_QUEUEING">
               <xsl:variable name="x_val11">
                 <xsl:value-of select="$margin_left+$bar_width*(position()-1)"/>
               </xsl:variable>
               <xsl:variable name="y_val11">
                 <xsl:value-of select="round(($graph_height)-($margin_bottom)-((($yval_min)-(self::node()))*(100 div (($yval_min)-($yval_max)))))"/>
               </xsl:variable>
               <xsl:value-of select="concat($x_val11,'','',$y_val11,'' '')"/>
             </xsl:for-each>
           </xsl:variable>
           <polyline points="{$v_path11}" style="fill:none;stroke:bisque;stroke-width:1" />
           <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_17b

Remarks:

  • In displaying the wait classes from C_OTHER to C_QUEUEING the color of a line can be the color of the last wait class with the same cumulated time waited if any,
  • Each wait class graph value is processed in a different “for-each” block.