Jan 12 2009

Execution Plan Hash Value in SQL Trace Files

Tag: 11gR1, SQL Trace, TVD$XTATChristian Antognini @ 12:10 pm

In a previous post I already pointed out that as of 11.1.0.7 new information is provided in the SQL trace files. One of them is the value “plh” in the PARSE, EXEC and FETCH lines. This new value provides the execution plan hash value. While adding this information to the output generated by TVD$XTAT I had to decide how to handle this new value. Hence, I executed the following test case in SQL*Plus…

  • I prepared the test environment by executing the following SQL statements:

ALTER SYSTEM FLUSH SHARED_POOL;

CREATE TABLE t 
AS 
SELECT rownum AS id, rpad('*',100,'*') AS pad 
FROM dual
CONNECT BY level <= 1000;

ALTER TABLE t ADD CONSTRAINT t_pk PRIMARY KEY (id);

EXECUTE dbms_stats.gather_table_stats(ownname=>user,tabname=>'t')

VARIABLE id NUMBER

  • I enabled SQL trace:

EXECUTE dbms_monitor.session_trace_enable(waits=>false,binds=>false)

EXECUTE :id := 10;

SELECT count(pad) FROM t WHERE id < :id;

EXECUTE :id := 990;

SELECT count(pad) FROM t WHERE id < :id;

SELECT count(pad) FROM t WHERE id < :id;

  • I disabled SQL trace and displayed the name of the trace file:

EXECUTE dbms_monitor.session_trace_disable

SELECT value 
FROM v$diag_info 
WHERE name = 'Default Trace File';

Now, let’s check the content of the trace file…

  • For the first query, the following information is provided. Notice that in the line PARSE the value of “plh” is “0″; in the line EXEC the value of “plh” is “4270555908″; in the lines PARSE and EXEC the value of “mis” is “1″ (the cursor was hard parsed); according to the execution plan (the line beginning with STAT; notice that I manually removed the runtime statistics and query optimizer estimations to keep the output more readable) the table was read through an index range scan.

PARSING IN CURSOR #2 len=39 dep=0 uid=83 oct=3 lid=83 tim=1231427339018492 hv=1107655156 ad='2e70b9cc' sqlid='asth1mx10aygn'
SELECT count(pad) FROM t WHERE id < :id
END OF STMT
PARSE #2:c=0,e=0,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=1,plh=0,tim=1231427339018492
EXEC #2:c=2000,e=0,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=1,plh=4270555908,tim=1231427339018492
FETCH #2:c=0,e=0,p=0,cr=3,cu=0,mis=0,r=1,dep=0,og=1,plh=4270555908,tim=1231427339018492
STAT #2 id=1 cnt=1 pid=0 pos=1 obj=0 op='SORT AGGREGATE'
STAT #2 id=2 cnt=9 pid=1 pos=1 obj=72373 op='TABLE ACCESS BY INDEX ROWID T'
STAT #2 id=3 cnt=9 pid=2 pos=1 obj=72374 op='INDEX RANGE SCAN T_PK'
FETCH #2:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=0,plh=4270555908,tim=1231427339018492
CLOSE #2:c=0,e=0,dep=0,type=0,tim=1231427339018492

  • For the second query, the following information is provided. Notice that in the lines PARSE and EXEC the value of “plh” is “4270555908″ (the same as the previous query) and the value of “mis” is “0″ (the cursor was not hard parsed), i.e. a cursor already present in the library cache was reused.

PARSING IN CURSOR #4 len=39 dep=0 uid=83 oct=3 lid=83 tim=1231427339018492 hv=1107655156 ad='2e70b9cc' sqlid='asth1mx10aygn'
SELECT count(pad) FROM t WHERE id < :id
END OF STMT
PARSE #4:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=4270555908,tim=1231427339018492
EXEC #4:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=4270555908,tim=1231427339018492
FETCH #4:c=0,e=0,p=0,cr=19,cu=0,mis=0,r=1,dep=0,og=1,plh=4270555908,tim=1231427339018492
STAT #4 id=1 cnt=1 pid=0 pos=1 obj=0 op='SORT AGGREGATE'
STAT #4 id=2 cnt=989 pid=1 pos=1 obj=72373 op='TABLE ACCESS BY INDEX ROWID T'
STAT #4 id=3 cnt=989 pid=2 pos=1 obj=72374 op='INDEX RANGE SCAN T_PK'
FETCH #4:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=0,plh=4270555908,tim=1231427339018492
CLOSE #4:c=0,e=0,dep=0,type=0,tim=1231427339018492

  • For the third query, the one taking advantage of extended cursor sharing, the following information is provided. Notice that in the line PARSE the value of “plh” is “4270555908″ (the same as the previous query) and the value of “mis” is “0″ (cursor was not hard parsed); in the line EXEC the value of “plh” is “2966233522″ and the value of “mis” is “1″ (cursor was hard parsed); according to the execution plan the table was read through a full table scan, i.e. not the same execution plan as the previous queries.

PARSING IN CURSOR #13 len=39 dep=0 uid=83 oct=3 lid=83 tim=1231427339018492 hv=1107655156 ad='2e70b9cc' sqlid='asth1mx10aygn'
SELECT count(pad) FROM t WHERE id < :id
END OF STMT
PARSE #13:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=4270555908,tim=1231427339018492
EXEC #13:c=0,e=0,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=1,plh=2966233522,tim=1231427339018492
FETCH #13:c=0,e=0,p=0,cr=19,cu=0,mis=0,r=1,dep=0,og=1,plh=2966233522,tim=1231427339018492
STAT #13 id=1 cnt=1 pid=0 pos=1 obj=0 op='SORT AGGREGATE'
STAT #13 id=2 cnt=989 pid=1 pos=1 obj=72373 op='TABLE ACCESS FULL T'
FETCH #13:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=0,plh=2966233522,tim=1231427339018492
CLOSE #13:c=0,e=0,dep=0,type=0,tim=1231427339018492

In summary, according to this test:

  • The value of “plh” in the line EXEC provides the hash value of the execution plan used to execute a SQL statement.
  • The value of “plh” in the line PARSE cannot be trusted.

Jan 05 2009

PerformaSure X-Agent Configuration

Tag: Quest PerformaSureChristian Antognini @ 7:47 pm

PerformaSure of Quest Software is a J2EE performance diagnosis tool that provides an end-to-end transaction-centric view of performance as experienced by end users. To gather profile information PerformaSure uses one or several agents deployed on the monitored systems. Since gathering profile information depends on the monitored component, three different agents are available:

  • System agent gather performance figures about the operating system.
  • Web server agents gather performance figures about a web server.
  • Application server agents gather detailed performance figures about an application server.

Since the agents are specific to each component, Quest Software clearly states which components are officially supported. For example, the current release (4.4) supports the following application servers: BEA WebLogic Server, IBM WebSphere Application Server, Oracle Application Server, JBoss Application Server and Apache Tomcat Server. Even if those are among the most commonly used, other application servers exist… For this reason PerformaSure also supports a generic agent called X-Agent. Although the X-Agent does not provide as much information as the other agents do, it might be very useful in some situations. The problem is that the documentation does not provide instructions on how to configure the it. Instead, it provides the following information:

“The X-Agent needs to be configured by Quest Consulting. For more information about customizing the X-Agent and modifying the startup sequence of the application server or standalone Java application that you want to instrument, contact your Quest sales representative.”

Ups! Not very useful…

To show you how such a configuration is performed, let me describe what I did few days ago on my Windows XP laptop to configure the X-Agent for Sun Java System Application Server 9.1 Update 2.

  • First of all, I opened a command prompt and I defined two environment variables pointing to the installation directories of Java and PerformaSure

c:\tmp>set JAVA_HOME=C:\Java\jdk\1.5.0
c:\tmp>set PERFORMASURE_HOME=C:\Java\quest\PerformaSure4.4.0

  • Then, in the same command prompt, I called the script preinstrumentor.cmd to create a JAR file that will be used during the startup of the application server

c:\tmp>call "%PERFORMASURE_HOME%\scripts\preinstrumentor.cmd" "%JAVA_HOME%"
2008-12-26 23:09:00.703 INFO  Loading Agent startup configuration from C:\Java\
  quest\PerformaSure4.4.0\config\agent.config
2008-12-26 23:09:02.031 INFO  PerformaSure 4.4 (Build PAS_440-20061024-1025) on
  Windows XP x86 5.1 using Sun Microsystems Inc. Java HotSpot(TM) Client VM
  version 1.5.0_10-b03 (extra info: mixed mode, sharing); Agent Type:
  Preinstrumentor
2008-12-26 23:09:02.062 INFO  Configured to connect to Nexus at localhost:41705
2008-12-26 23:09:02.187 INFO  Connected to Nexus at localhost:41705
2008-12-26 23:09:03.203 INFO  Agent started
2008-12-26 23:09:03.203 INFO  Creating bootstrap classes in C:\Java\quest\Perfo
  rmaSure4.4.0\scripts\..\bootstrap\C--Java-jdk-1.5.0.jar
2008-12-26 23:09:05.796 INFO  Preinstrumentation complete
2008-12-26 23:09:05.812 INFO  Preinstrumentor Agent shutdown completed

  • The last operation I performed through the command prompt was the “generation” of two Java options (-Xbootclasspath and -javaagent) to be used in the configuration of the application server (it is not necessary to do it in this way, but with that method it’s possible to avoid annoying typos…)

C:\Tmp>call "%PERFORMASURE_HOME%\scripts\makebootstrappath.cmd" "%JAVA_HOME%"
C:\Tmp>echo -Xbootclasspath/p:"%PS_BOOTSTRAP_PATH%"
-Xbootclasspath/p:"C:\Java\quest\PerformaSure4.4.0\bootstrap\C--Java-jdk-1.5.0.jar"
C:\Tmp>echo -javaagent:"%PERFORMASURE_HOME%\lib\performasure-agent.jar"
-javaagent:"C:\Java\quest\PerformaSure4.4.0\lib\performasure-agent.jar"

  • To finish the configuration I added, through the administration console of the application server, the following JVM options (click here to see an image of the relevant part of the console)

-Dperformasure.agent.appserverinfo=kalgan:Generic:SunAS9
-Dperformasure.debug=0
-Xbootclasspath/p:"C:\Java\quest\PerformaSure4.4.0\bootstrap\C--Java-jdk-1.5.0.jar"
-javaagent:"C:\Java\quest\PerformaSure4.4.0\lib\performasure-agent.jar"

Notice that the value of the variable performasure.agent.appserverinfo has the following format: <server>:Generic:<version>.

After these operations I restarted the application server and, as a result, I was able to use PerformaSure to profile the applications running into the JVM of the application server.