Using Dynamic Statement Cache in DB2 9.1 for z/Os
Upcoming SlideShare
Loading in...5
×
 

Using Dynamic Statement Cache in DB2 9.1 for z/Os

on

  • 528 views

Using the table DSN_STATEMENT_CACHE_TABLE can be of valuable help when trying to diagnose performance problems in DB2 for z/Os. ...

Using the table DSN_STATEMENT_CACHE_TABLE can be of valuable help when trying to diagnose performance problems in DB2 for z/Os.
A brief guide to start using it and a general description of how it works.

Statistics

Views

Total Views
528
Views on SlideShare
528
Embed Views
0

Actions

Likes
0
Downloads
2
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Using Dynamic Statement Cache in DB2 9.1 for z/Os Using Dynamic Statement Cache in DB2 9.1 for z/Os Document Transcript

  • 1 Using Dynamic Statement Cache in DB2 9.1 for z/Os By César M. Buzzo (Senior Database Administrator) There are a number of explain tables that can be used for diagnose or performance purposes. One of them is DSN_STATEMENT_CACHE_TABLE. You can find the sql statements for creating an instance of this table and other objects in members DSNTESC and DSNTIJOS of the SDSNSAMP library. This is the structure of the table according to IBM documentation: http://pic.dhe.ibm.com/infocenter/dzichelp/v2r2/index.jsp?topic=%2Fcom.ibm.db2z9.doc.p erf%2Fsrc%2Ftpc%2Fdb2z_dsnstatementcachetable.htm Once you have an instance of this table – remember that you can have as many as you want provided they have different qualifiers!, you can start using it. Your current SQLID determines the qualifier of DSN_STATEMENT_CACHE_TABLE your going to use. Let’s see some important steps to take into account before retrieving information from the table: 1) Activation of performance trace (IFCID 318) You need to start a performance trace with IFCID 318 in order to have the table DSN_STATEMENT_CACHE_TABLE populated with useful information after executing EXPLAIN STMTCACHE ALL. Here is an example of the command to start the trace: -START TRACE(PERFM) CLASS(30) IFCID(318) Why is this trace so important? Well, if you do not start this trace, you can only get the sql text (STMT_TEXT column) of the statements in cache, but the values for the rest of the numeric columns that account for performance statistics will remain null (or zero in fact). So, if you want to know how many times a sql statement was executed, or the number of getpage operations or index scans the statement performed, you need to start the trace. Statistics reset when the trace is stopped! The column STAT_TS in DSN_STATEMENT_CACHE_TABLE contains the timestamp when IFCID 318 is started.
  • 2 2) ZPARM Parameters CACHEDYN = YES is necessary for the dynamic statements to be inserted in the global cache. EDMSTMTC: used to specify the EDM Statement Pool size. MAXKEEPD: specifies the maximum number of prepared, dynamic SQL statements that are to be saved past a commit point. This parameter applies to applications that run with the KEEPDYNAMIC(YES) bind option. 3) Take a snapshot of the statement cache into DSN_STATEMENT_CACHE_TABLE Dynamic statements are cached in the EDM statement pool wich belongs to the EDM storage and resides entirely above the bar, so is not critical as a virtual storage constraint. EXPLAIN STMTCACHE ALL: This is the sql statement that populates the table DSN_STATEMENT_CACHE_TABLE. It inserts one row for each entry in the dynamic statement cache. The column EXPLAIN_TS in DSN_STATEMENT_CACHE_TABLE contains the time when EXPLAIN STMTCACHE ALL was executed. So, executing EXPLAIN STMTCACHE ALL is like taking a snapshot of your statement cache. You can track a specific sql statement (filter by column STMT_ID) along different cache snapshots (filter by column EXPLAIN_TS), and calculate the activity that took place between both snapshots for the statement. As counters only increase with time (as long as the performance trace is active), you have to substract the values of the first snapshot to the values of the second one to get the net activity that took place for that statement for the period of time between both snapshots. For example, the query below gets the net activity for all staments in cache that had some activity between cache snapshots (elapsed time of 24 hours in this case): -- Get net activity for all statements between two cache snapshots SELECT S2.STMT_ID, S2.PROGRAM_NAME, S2.PRIMAUTH, S2.CURSQLID, S2.BIND_QUALIFIER, S2.BIND_ISO, S2.SCHEMA, S2.STAT_TS, S2.CACHED_TS, S1.EXPLAIN_TS EXPLAN_TS_1, S2.EXPLAIN_TS EXPLAN_TS_2, S2.STAT_EXEC - S1.STAT_EXEC DIF_STAT_EXEC, S2.STAT_GPAG - S1.STAT_GPAG DIF_STAT_GPAG, S2.STAT_SYNR - S1.STAT_SYNR DIF_STAT_SYNR, S2.STAT_WRIT - S1.STAT_WRIT DIF_STAT_WRIT,
  • 3 S2.STAT_EROW - S1.STAT_EROW DIF_STAT_EROW, S2.STAT_PROW - S1.STAT_PROW DIF_STAT_PROW, S2.STAT_SORT - S1.STAT_SORT DIF_STAT_SORT, S2.STAT_INDX - S1.STAT_INDX DIF_STAT_INDX, S2.STAT_RSCN - S1.STAT_RSCN DIF_STAT_RSCN, S2.STAT_PGRP - S1.STAT_PGRP DIF_STAT_PGRP, S2.STAT_ELAP - S1.STAT_ELAP DIF_STAT_ELAP, S2.STAT_CPU - S1.STAT_CPU DIF_STAT_CPU, S2.STAT_SUS_SYNIO - S1.STAT_SUS_SYNIO DIF_STAT_SUS_SYNIO, S2.STAT_SUS_LOCK - S1.STAT_SUS_LOCK DIF_STAT_SUS_LOCK, S2.STAT_SUS_SWIT - S1.STAT_SUS_SWIT DIF_STAT_SUS_SWIT, S2.STAT_SUS_GLCK - S1.STAT_SUS_GLCK DIF_STAT_SUS_GLCK, S2.STAT_SUS_OTHR - S1.STAT_SUS_OTHR DIF_STAT_SUS_OTHR, S2.STAT_SUS_OTHW - S1.STAT_SUS_OTHW DIF_STAT_SUS_OTHW, S2.STAT_RIDLIMT - S1.STAT_RIDLIMT DIF_STAT_RIDLIMT, S2.STAT_RIDSTOR - S1.STAT_RIDSTOR DIF_STAT_RIDSTOR, CAST(S2.STMT_TEXT AS VARCHAR(4000)) STMT_TEXT FROM DSN_STATEMENT_CACHE_TABLE S2 LEFT OUTER JOIN DSN_STATEMENT_CACHE_TABLE S1 ON S2.STMT_ID = S1.STMT_ID WHERE –- Date of the first snapshot CAST(S1.EXPLAIN_TS AS DATE) = CAST('6/18/2013' AS DATE) -- Time of the first snapshot AND CAST(S1.EXPLAIN_TS AS TIME) = CAST('09:01:12' AS TIME) -- Date of the second snapshot AND CAST(S2.EXPLAIN_TS AS DATE) = CAST('6/19/2013' AS DATE) -- Time of the second snapshot AND CAST(S2.EXPLAIN_TS AS TIME) = CAST('09:03:24' AS TIME) -- Snapshots are different and S1 preceeds S2 AND S1.EXPLAIN_TS < S2.EXPLAIN_TS -- Required performance trace active before first snapshot AND S1.EXPLAIN_TS >= S1.STAT_TS -- Required performance trace active before second snapshot AND S2.EXPLAIN_TS >= S2.STAT_TS -- Trace was running continuously before both snapshots AND S1.STAT_TS = S2.STAT_TS -- Filter only statements that had activity between snapshots AND (S2.STAT_EXEC - S1.STAT_EXEC > 0 OR S2.STAT_GPAG - S1.STAT_GPAG > 0 OR S2.STAT_SYNR - S1.STAT_SYNR > 0 OR S2.STAT_WRIT - S1.STAT_WRIT > 0 OR S2.STAT_EROW - S1.STAT_EROW > 0 OR S2.STAT_PROW - S1.STAT_PROW > 0 OR S2.STAT_SORT - S1.STAT_SORT > 0 OR S2.STAT_INDX - S1.STAT_INDX > 0 OR S2.STAT_RSCN - S1.STAT_RSCN > 0 OR S2.STAT_PGRP - S1.STAT_PGRP > 0 OR S2.STAT_ELAP - S1.STAT_ELAP > 0 OR S2.STAT_CPU - S1.STAT_CPU > 0 OR S2.STAT_SUS_SYNIO - S1.STAT_SUS_SYNIO > 0 OR S2.STAT_SUS_LOCK - S1.STAT_SUS_LOCK > 0 OR S2.STAT_SUS_SWIT - S1.STAT_SUS_SWIT > 0 OR S2.STAT_SUS_GLCK - S1.STAT_SUS_GLCK > 0 OR S2.STAT_SUS_OTHR - S1.STAT_SUS_OTHR > 0 OR S2.STAT_SUS_OTHW - S1.STAT_SUS_OTHW > 0 OR S2.STAT_RIDLIMT - S1.STAT_RIDLIMT > 0 OR S2.STAT_RIDSTOR - S1.STAT_RIDSTOR > 0) WITH UR The only drawback of the above query is that some statements may have been flushed out of cache by the time of the second snapshot. This can be caused by: View slide
  • 4 - Drop or Alter of an object - Revoke authorization - Runstats - LRU: Least recently used (take a look at EDMSTMTC parameter) Below there is another query to get the average of all statistics columns for a snapshot: -- Get average values for the different statistics columns of a cache snapshot SELECT STMT_ID, PROGRAM_NAME, PRIMAUTH, CURSQLID, BIND_QUALIFIER, BIND_ISO, SCHEMA, STAT_TS, CACHED_TS, EXPLAIN_TS, STAT_EXEC, CAST((STAT_GPAG / STAT_EXEC) AS NUMERIC(30,2)) AVG_GPAG, CAST((STAT_SYNR / STAT_EXEC) AS NUMERIC(30,2)) AVG_SYNR, CAST((STAT_WRIT / STAT_EXEC) AS NUMERIC(30,2)) AVG_WRIT, CAST((STAT_EROW / STAT_EXEC) AS NUMERIC(30,2)) AVG_EROS, CAST((STAT_PROW / STAT_EXEC) AS NUMERIC(30,2)) AVG_PROW, CAST((STAT_SORT / STAT_EXEC) AS NUMERIC(30,2)) AVG_SORT, CAST((STAT_INDX / STAT_EXEC) AS NUMERIC(30,2)) AVG_INDX, CAST((STAT_RSCN / STAT_EXEC) AS NUMERIC(30,2)) AVG_RSCN, CAST((STAT_PGRP / STAT_EXEC) AS NUMERIC(30,2)) AVG_PGRP, CAST((STAT_ELAP / STAT_EXEC) AS NUMERIC(30,2)) AVG_ELAP, CAST((STAT_CPU / STAT_EXEC) AS NUMERIC(30,2)) AVG_CPU, CAST((STAT_SUS_SYNIO / STAT_EXEC) AS NUMERIC(30,2)) AVG_SUS_SYNIO, CAST((STAT_SUS_LOCK / STAT_EXEC) AS NUMERIC(30,2)) AVG_SUS_LOCK, CAST((STAT_SUS_SWIT / STAT_EXEC) AS NUMERIC(30,2)) AVG_SUS_SWIT, CAST((STAT_SUS_GLCK / STAT_EXEC) AS NUMERIC(30,2)) AVG_SUS_GLCK, CAST((STAT_SUS_OTHR / STAT_EXEC) AS NUMERIC(30,2)) AVG_SUS_OTHR, CAST((STAT_SUS_OTHW / STAT_EXEC) AS NUMERIC(30,2)) AVG_SUS_OTHW, CAST((STAT_RIDLIMT / STAT_EXEC) AS NUMERIC(30,2)) AVG_RIDLIMT, CAST((STAT_RIDSTOR / STAT_EXEC) AS NUMERIC(30,2)) AVG_RIDSTOR, CAST(STMT_TEXT AS VARCHAR(2000)) STMT_TEXT FROM DSN_STATEMENT_CACHE_TABLE WHERE –- Date of the snapshot CAST(EXPLAIN_TS AS DATE) = CAST('6/19/2013' AS DATE) -- Time of the snapshot AND CAST(EXPLAIN_TS AS TIME) = CAST('15:25:12' AS TIME) -- Required performance trace active before snapshot AND EXPLAIN_TS >= STAT_TS -- This condition is necessary to avoid division by zero! AND STAT_EXEC > 0 Therea are also other EXPLAIN options like EXPLAIN STMTCACHE STMTID and EXPLAIN STMTCACHE STMTTOKEN that populate other tables besides DSN_STATEMENT_CACHE_TABLE, and that can be of valuable help for specific sql statements analysis, but they are out of the scope of this document. Recommendations: View slide
  • 5 - Keep an eye on the number of rows of DSN_STATEMENT_CACHE. Every snapshot can add thousands of rows to the table, so I recommend to delete rows belonging to old snapshots from time to time. Below is a query to identify the snapshots in the table and the statements (rows) that each one has. Note that the rows of a snapshot have the same value for EXPLAIN_TS column. SELECT EXPLAIN_TS, COUNT(*) TOTALROWS FROM DSN_STATEMENT_CACHE_TABLE GROUP BY EXPLAIN_TS ORDER BY EXPLAIN_TS WITH UR Delete a snapshot from time to time: DELETE FROM DSN_STATEMENT_CACHE_TABLE WHERE –- Date of the snapshot CAST(EXPLAIN_TS AS DATE) = CAST('6/18/2013' AS DATE) -- Time of the snapshot AND CAST(EXPLAIN_TS AS TIME) = CAST('09:01:12' AS TIME) - As a consequence of the previous recommendation, it is also advisable to REORG the tablespace that contains DSN_STATEMENT_CACHE_TABLE, specially after deleting snapshots.