DB2 10.5 for Linux, UNIX, and Windows

Exercise 4: Differentiating activities by activity type

This exercise demonstrates how a work action set can be used to: Collect information about all activities of a certain type; apply a threshold to all activities of a certain type; isolate activities of a certain type by mapping them to a specific service subclass 

Estimated time: 25-30 minutes

Work action sets are used to apply an action to an activity based on what the activity is doing rather than who submitted it (as is done with workloads).

Actions can be applied to either:

This exercise shows both methods.

Additional Information: There are other actions that can be applied, such as collecting statistics for activities of a certain type that are not covered in this exercise.

Step 1: Create a work class set

First, create a work class set containing work classes that will represent the specific types of activities you are interested in. This work class set will be used in conjunction with work action sets to perform actions on the selected types of activities. The following example creates a work class set containing work classes of all possible types, but if you were interested only in one activity type, your work class set could be created to only contain that one work class.

CREATE WORK CLASS SET all_class_types
    (WORK CLASS read_wc WORK TYPE READ,
     WORK CLASS write_wc WORK TYPE WRITE,
     WORK CLASS ddl_wc WORK TYPE DDL,
     WORK CLASS call_wc WORK TYPE CALL,
     WORK CLASS load_wc WORK TYPE LOAD,
     WORK CLASS all_wc WORK TYPE ALL POSITION LAST)

Step 2: Enable the activities event monitor

Enable the event monitor for activities that was created in Exercise 1.

SET EVENT MONITOR DB2ACTIVITIES STATE 1

Step 3: Create a database work action set

If you want to perform a particular action on all activities of a specific type (such as applying a threshold or collecting activity information), use a database work action set.

Create a work action set at the database level that contains work actions for the specific work class representing the type of activities you want isolated. For this example, we want to collect activity data for all DDL, READ and LOAD activities that run on the system and we also want to stop any large read activity from running. For this exercise, a large read activity is any select statement that has an estimated cost (in timerons) of greater than 10000.

CREATE WORK ACTION SET db_was FOR DATABASE
   USING WORK CLASS SET  all_class_types
   (WORK ACTION collect_load_wa ON WORK CLASS load_wc
       COLLECT ACTIVITY DATA WITH DETAILS AND VALUES,
    WORK ACTION collect_ddl_wa ON WORK CLASS ddl_wc
       COLLECT ACTIVITY DATA WITH DETAILS AND VALUES,
    WORK ACTION collect_read_wa ON WORK CLASS read_wc
       COLLECT ACTIVITY DATA WITH DETAILS AND VALUES,
    WORK ACTION stop_large_read_wa on WORK CLASS read_wc
       WHEN ESTIMATEDSQLCOST > 10000 STOP EXECUTION )

Step 4: Run activities and view work action set statistics

Run the work1.db2  and work3.db2 scripts.

db2 -o -tvf work1.db2
db2 -o -tvf work3.db2

You can use the WLM_GET_WORK_ACTION_SET_STATS table function to access the work action set statistics in memory to get the number of times specific activity types have been run. Note that running the following query shows only the load_wc, read_wc and ddl_wc work classes since they are the only work classes that have an applicable work action. All the other activities are counted under the "*":

CONNECT TO SAMPLE

SELECT SUBSTR(WORK_ACTION_SET_NAME, 1, 12) AS WORK_ACTION_SET_NAME,
         SUBSTR(WORK_CLASS_NAME, 1, 12) AS WORK_CLASS_NAME,
         LAST_RESET,
         SUBSTR(CHAR(ACT_TOTAL), 1, 10) AS TOTAL_ACTS
FROM TABLE(WLM_GET_WORK_ACTION_SET_STATS('', -2)) AS WASSTATS
ORDER BY WORK_ACTION_SET_NAME, WORK_CLASS_NAME

The output will look something like:

WORK_ACTION_SET_NAME WORK_CLASS_NAME  LAST_RESET                TOTAL_ACTS
-------------------- ---------------- ------------------------- ----------
DB_WAS               *                2007-08-15-19.02.47.305556 12
DB_WAS               DDL_WC           2007-08-15-19.02.47.305556 12
DB_WAS               LOAD_WC          2007-08-15-19.02.47.305556 1
DB_WAS               READ_WC          2007-08-15-19.02.47.305556 13

  4 record(s) selected.

Step 5: View the activity data collected

Information about every individual DDL, READ and LOAD activities was collected by the activities event monitor, due to the specification of the COLLECT ACTIVITY DATA work action that was applied to the ddl_wc, read_wc, and the load_wc work classes in step 3. The following are a couple of examples of how you might want to look at this activity information. 

To get some basic information about the activities, you can simply query the activity event monitor table with a statement such as the following:

SELECT ACTIVITY_ID,
                SUBSTR(ACTIVITY_TYPE, 1, 8) AS ACTIVITY_TYPE,
                VARCHAR(APPL_ID, 30) AS APPL_ID,
                VARCHAR(APPL_NAME, 10) AS APPL_NAME
FROM ACTIVITY_DB2ACTIVITIES

The output will look something like:

ACTIVITY_ID          ACTIVITY_TYPE APPL_ID                        APPL_NAME
-------------------- ------------- ------------------------------ ----------
                   1 READ_DML      *LOCAL.karenam.070815192410    db2bp
                   1 READ_DML      *LOCAL.karenam.070815192418    db2bp
                   2 READ_DML      *LOCAL.karenam.070815192418    db2bp
                   3 READ_DML      *LOCAL.karenam.070815192418    db2bp
                   4 READ_DML      *LOCAL.karenam.070815192418    db2bp
                   1 DDL           *LOCAL.karenam.070815192418    db2bp
                   2 DDL           *LOCAL.karenam.070815192418    db2bp
                   3 DDL           *LOCAL.karenam.070815192418    db2bp
                   2 READ_DML      *LOCAL.karenam.070815192418    db2bp
                   1 READ_DML      *LOCAL.karenam.070815192418    db2bp
                   2 READ_DML      *LOCAL.karenam.070815192418    db2bp
                   3 READ_DML      *LOCAL.karenam.070815192418    db2bp
                   4 READ_DML      *LOCAL.karenam.070815192418    db2bp
                   6 LOAD          *LOCAL.karenam.070815192418    db2bp
                   1 DDL           *LOCAL.karenam.070815192418    db2bp
                   1 DDL           *LOCAL.karenam.070815192418    db2bp
                   2 DDL           *LOCAL.karenam.070815192418    db2bp
                   3 DDL           *LOCAL.karenam.070815192418    db2bp
                   4 DDL           *LOCAL.karenam.070815192418    db2bp
                   5 READ_DML      *LOCAL.karenam.070815192418    db2bp
                  10 READ_DML      *LOCAL.karenam.070815192418    db2bp
                   1 DDL           *LOCAL.karenam.070815192418    db2bp
                   2 DDL           *LOCAL.karenam.070815192418    db2bp
                   3 DDL           *LOCAL.karenam.070815192418    db2bp
                   4 DDL           *LOCAL.karenam.070815192418    db2bp
                   1 READ_DML      *LOCAL.karenam.070815192426    db2bp

  26 record(s) selected.

To obtain additional information about each activity, such as activity text and what service class it ran under, you can perform a query similar to this one:

SELECT VARCHAR(A.APPL_NAME, 15) as APPL_NAME,
                 VARCHAR(A.TPMON_CLIENT_APP, 20) AS CLIENT_APP_NAME,
                 VARCHAR(A.APPL_ID, 30) as APPL_ID,
                 VARCHAR(A.SERVICE_SUPERCLASS_NAME, 20) as SUPER_CLASS,
                 VARCHAR(A.SERVICE_SUBCLASS_NAME, 20) as SUB_CLASS,
                 SQLCODE,
                 VARCHAR(S.STMT_TEXT, 300) AS STMT_TEXT
FROM ACTIVITY_DB2ACTIVITIES AS A, ACTIVITYSTMT_DB2ACTIVITIES AS S
WHERE A.APPL_ID = S.APPL_ID AND
                A.ACTIVITY_ID = S.ACTIVITY_ID AND
                A.UOW_ID = S.UOW_ID

The output will look something like:

APPL_NAME       CLIENT_APP_NAME      APPL_ID                       
SUPER_CLASS
         SUB_CLASS            SQLCODE     STMT_TEXT
--------------- -------------------- ------------------------------ ---------
---
-------- -------------------- ----------- -----------------------------------
---
-----------------------------------------------------------------------------
---
-----------------------------------------------------------------------------
---
-----------------------------------------------------------------------------
---
----------------------
db2bp           CLP wasdbsc.db2      *LOCAL.karenam.070815192410   
SYSDEFAULTUS
ERCLASS  SYSDEFAULTSUBCLASS             0 SELECT DISTINCT CURRENT SQLID FROM
SYS
IBM.SYSTABLES

db2bp           CLP work1.db2        *LOCAL.karenam.070815192418   
SYSDEFAULTUS
ERCLASS  SYSDEFAULTSUBCLASS             0 values(current client_applname)

      :
      :
db2bp           CLP work1.db2        *LOCAL.karenam.070815192418   
SYSDEFAULTUS
ERCLASS  SYSDEFAULTSUBCLASS             0 drop procedure stp2


db2bp           CLP work3.db2        *LOCAL.karenam.070815192426   
SYSDEFAULTUS
ERCLASS  SYSDEFAULTSUBCLASS         -4712 select count(*) from syscat.tables,
sy
scat.tables, syscat.tables, syscat.tables, syscat.tables, syscat.tables

      :
      :

Note that one of the activities has an SQLCODE of -4712. This indicates execution of the activity was stopped due to a threshold violation. The threshold defined for the stop_large_read_wa work action will prevent any SELECT statement with an estimated cost of greater than 10000 from executing.

Additional information: Load activities (not including load from a cursor) do not have an entry in the activity statement event monitor table  (activitystmt_db2activities table) which explains why there is no record for the single load activity that is run by the work1.db2 script in the output shown previously in the last query. The reason for this is that load activities are not SQL statements. For load from cursor activities, there is an entry for the cursor statement in the activity statement event monitor table because the cursor itself is a separate activity. There is an entry for all load activities in the activities event monitor table (activity_db2activities). 

Step 6: Disable work actions

Before moving on to the service class work action set, drop the database work action set.

DROP WORK ACTION SET db_was

Additional information: Before dropping any concurrency threshold, that threshold must first be disabled. In this case, there are no work actions that represent a concurrency threshold but if there were, the only way to disable it would be by disabling the work action. A work action threshold cannot be manipulated through THRESHOLD SQL statements; they can be manipulated only through WORK ACTION SET SQL statements. Only work actions that represent concurrency thresholds need to be disabled before dropping the subsequent work action set. For this exercise, because there are no work actions that represent a concurrency threshold, there is no need to disable any of the work actions before dropping the work action set.

If you want to apply a particular action, such as a threshold, to all the activities of a certain type running in a service super class, you should consider using a service class work action set. You can create a mapping work action to map specific types of activities to a specific service subclass and then apply a threshold to that service subclass.  The following steps demonstrate how service class work action sets might be used

Step 7: Create a service class to and create a workload

Create a service subclass under the work1_sc service super class that was created in Exercise 2 Step 2.

The service super class work1_sc  is the service class that the activities will be mapped to through the workloads. The service subclass work1_sc_read is the service class that the read activities will be mapped to through the work action.

CREATE SERVICE CLASS work1_sc_read UNDER work1_sc

Create a workload so that all activities submitted by the work3.db2 script will be mapped to work1_sc service super class. Note that activities from work1.db2 are already being mapped to work1_sc from one of the previous exercises.

CREATE WORKLOAD work3_wl CURRENT CLIENT_APPLNAME('CLP work3.db2')
   SERVICE CLASS work1_sc

Step 8: Create a service class work action set

Create a work action set at the service class level that contains work actions that apply to the specific work classes representing the types of activities you want isolated. For this example, we want to collect activity data for all DDL, read, and load activities that run under the work1_sc service class and we also want to map read activities to a separate service subclass so that we can treat them differently; in this case, a threshold will be applied to the service subclass to stop any large SELECT statements from running.

CREATE WORK ACTION SET sc_was FOR SERVICE CLASS work1_sc 
  USING WORK CLASS SET all_class_types (
    WORK ACTION collect_load_wa ON WORK CLASS load_wc
      COLLECT ACTIVITY DATA ON ALL MEMBERS WITH DETAILS AND VALUES,
    WORK ACTION collect_ddl_wa ON WORK CLASS ddl_wc
      COLLECT ACTIVITY DATA ON ALL MEMBERS WITH DETAILS AND VALUES,
   WORK ACTION collect_read_wa ON WORK CLASS read_wc
      COLLECT ACTIVITY DATA ON ALL MEMBERS WITH DETAILS AND VALUES,
   WORK ACTION map_read_wa on WORK CLASS read_wc
           MAP ACTIVITY TO work1_sc_read)

Step 9: Create a service class threshold

To get an effect similar to the stop_large_read_wa work action that prevented any large SELECT statements from running, create an ESTIMATEDSQLCOST threshold and apply it to the work1_sc_read service subclass.

CREATE THRESHOLD stop_large_activities FOR SERVICE CLASS work1_sc_read
              UNDER work1_sc
              ACTIVITIES ENFORCEMENT DATABASE
              WHEN ESTIMATEDSQLCOST >10000 STOP EXECUTION

Step 10: Clear the activity tables, reset the statistics, and run activities

Clear out all of the activity tables so that you can start afresh before running the script again. Then call the wlm_collect_stats() stored procedure to reset the statistics

DELETE FROM activity_db2activities
DELETE FROM activitystmt_db2activities
DELETE FROM activityvals_db2activities

CALL wlm_collect_stats()

Now, run work1.db2  and work3.db2 scripts once.

db2 -o -tvf work1.db2
db2 -o -tvf work3.db2

Note the SQL04712 error for activities that caused the threshold to be exceeded.

Step 11: View work action set statistics

Use the WLM_GET_WORK_ACTION_SET_STATS table function to access the work action set statistics in memory to get the number of times specific activity types have been run. Note that running the following query shows only the load_wc, ddl_wc, and the read_wc work classes since they are the only three work classes that have a work action applied to them. All the other activities end up being counted under "*":

CONNECT TO SAMPLE

SELECT SUBSTR(WORK_ACTION_SET_NAME, 1, 12) AS WORK_ACTION_SET_NAME,
               SUBSTR(CHAR(MEMBER), 1, 4) AS MEMB,
               SUBSTR(WORK_CLASS_NAME, 1, 12) AS WORK_CLASS_NAME, LAST_RESET,
               SUBSTR(CHAR(ACT_TOTAL), 1, 10) AS TOTAL_ACTS
FROM TABLE(WLM_GET_WORK_ACTION_SET_STATS('', -2)) AS WASSTATS
ORDER BY WORK_ACTION_SET_NAME, WORK_CLASS_NAME, MEMB

This time, output will look something such as the following:

WORK_ACTION_SET_NAME MEMB WORK_CLASS_NAME LAST_RESET                 TOTAL_ACTS
-------------------- ---- --------------- -------------------------- ----------
SC_WAS               0    *               2007-08-15-19.02.54.597999 12
SC_WAS               0    DDL_WC          2007-08-15-19.02.54.597999 12
SC_WAS               0    LOAD_WC         2007-08-15-19.02.54.597999 1
SC_WAS               0    READ_WC         2007-08-15-19.02.54.597999 12

  4 record(s) selected.

Step 12: View the activity data collected

Now query the activity tables again to get information about the individual activities.  Note the service subclass that the activities were run under.

SELECT VARCHAR(A.APPL_NAME, 15) as APPL_NAME,
                 VARCHAR(A.TPMON_CLIENT_APP, 20) AS CLIENT_APP_NAME,
                 VARCHAR(A.APPL_ID, 30) as APPL_ID,
                 VARCHAR(A.SERVICE_SUPERCLASS_NAME, 20) as SUPER_CLASS,
                 VARCHAR(A.SERVICE_SUBCLASS_NAME, 20) as SUB_CLASS,
                 SQLCODE,
                 VARCHAR(S.STMT_TEXT, 300) AS STMT_TEXT
FROM ACTIVITY_DB2ACTIVITIES AS A, ACTIVITYSTMT_DB2ACTIVITIES AS S
WHERE A.APPL_ID = S.APPL_ID AND
                A.ACTIVITY_ID = S.ACTIVITY_ID AND
                A.UOW_ID = S.UOW_ID

The output will look something like:

APPL_NAME       CLIENT_APP_NAME      APPL_ID                        SUPER_CLASS
         SUB_CLASS            SQLCODE     STMT_TEXT
--------------- -------------------- ------------------------------ ------------
-------- -------------------- ----------- --------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
----------------------

db2bp           CLP work1.db2        *LOCAL.karenam.070815195555    WORK1_SC
         WORK1_SC_READ                   0 values(current client_applname)

db2bp           CLP work1.db2        *LOCAL.karenam.070815195555    WORK1_SC
         WORK1_SC_READ                   0 select * from org
:
:
db2bp           CLP work1.db2        *LOCAL.karenam.070815195555    WORK1_SC
         SYSDEFAULTSUBCLASS             0 drop procedure stp2

db2bp           CLP work3.db2        *LOCAL.karenam.070815195600    WORK1_SC
         WORK1_SC_READ               -4712 select count(*) from syscat.tables, sy
scat.tables, syscat.tables, syscat.tables, syscat.tables, syscat.tables

Note again, that one of the activities has a SQLCODE of -4712, this time because of the stop_large_activities service class threshold that was created in step 9 that was violated because the estimated cost for that select statement was too large. Also notice that all read activities are being run under the work1_sc_read service subclass.

Step 13: Reset for next exercise

Disable the even monitor, drop the service class threshold and drop the service class work action set.

SET EVENT MONITOR DB2ACTIVITIES STATE 0

DROP THRESHOLD STOP_LARGE_ACTIVITIES
ALTER WORK ACTION SET SC_WAS
	ALTER WORK ACTION COLLECT_LOAD_WA DISABLE
	ALTER WORK ACTION COLLECT_DDL_WA DISABLE
	ALTER WORK ACTION COLLECT_READ_WA DISABLE
	ALTER WORK ACTION MAP_READ_WA DISABLE;
DROP WORK ACTION SET SC_WAS

Clear out all of the activity tables so that you can start afresh, before running the script again. 

DELETE FROM activity_db2activities
DELETE FROM activitystmt_db2activities
DELETE from activityvals_db2activities

Disable all of the workloads that have been created so that all activities will run under the default user workload and get mapped to the default service super class.

ALTER WORKLOAD work1_wl DISABLE
ALTER WORKLOAD work2_wl DISABLE
ALTER WORKLOAD work3_wl DISABLE
ALTER WORKLOAD workth_wl DISABLE

Call the wlm_collect_stats() stored procedure to reset the statistics.

CALL WLM_COLLECT_STATS()