The purpose of this blog is to show how different performance strategies can be implemented using the Oracle Database Resource Manager. Some practical examples are looked at to illustrate the point.
Resource Manager is designed to maximize throughput, so the resource plan directive given is no hard limit. In a CPU constrained system, we can allocate more CPU resources to OLTP users than to batch-jobs. With Resource Manager, the DBA can plan for a more proactive and predictable performance perspective – meeting service level agreements
In previous blog “2014-01 – The Oracle Resource Manager“ we created our customer resource manager plan called ‘Z_DEFAULT_PLAN’.
The plan directives were set as follows:
SQL> SET LINESIZE 100
SQL> COL plan FORMAT a15
SQL> COL group_or_subplan FORMAT a15
SQL> SELECT plan,
2 group_or_subplan,
3 type,
4 cpu_p1,
5 status
6 FROM dba_rsrc_plan_directives
7 WHERE plan='Z_DEFAULT_PLAN'
8 ORDER BY 1,2,3,4;
PLAN GROUP_OR_SUBPLA TYPE CPU_P1 STATUS
--------------- --------------- -------------- ---------- ----------
Z_DEFAULT_PLAN OTHER_GROUPS CONSUMER_GROUP 5
Z_DEFAULT_PLAN SYS_GROUP CONSUMER_GROUP 15
Z_DEFAULT_PLAN Z_TEST_APPL CONSUMER_GROUP 30
Verify if Z_DEFAULT_PLAN is turned on:
SQL> SELECT name, is_top_plan
2 FROM v$rsrc_plan
3 WHERE is_top_plan = 'TRUE';
NAME IS_TO
-------------------------------- -----
DEFAULT_MAINTENANCE_PLAN TRUE
We want to activate the Z_DEFAULT_PLAN immediately as our default plan:
SQL> ALTER SYSTEM SET resource_manager_plan = z_default_plan;
System altered.
SQL> SELECT name, is_top_plan
2 FROM v$rsrc_plan
3 WHERE is_top_plan = 'TRUE';
NAME IS_TO
-------------------------------- -----
Z_DEFAULT_PLAN TRUE
We will need some executable code capable to load the CPU close to 100% (CPU BOUND).
The “TEST” database user will be used to perform the practical samples.
Create the following PL/SQL store procedure as sample code:
SQL> CREATE OR REPLACE PROCEDURE test.z_test AS
2 t_inicio DATE;
3 elapsed_time NUMBER DEFAULT 0;
4 t_final DATE;
5 contador NUMBER DEFAULT 0;
6 BEGIN
7
8 dbms_output.put_line(' ') ;
9 dbms_output.put_line('executing z_test ...') ;
10
11 t_inicio := sysdate ;
12 dbms_output.put_line('Process Start: ') ;
13 dbms_output.put_line(to_char(t_inicio,'yyyy-mm-dd hh24:mi:ss')) ;
14
15 /* test code - begin */
16
17 WHILE elapsed_time < 20 LOOP
18 t_final := SYSDATE;
19
20 elapsed_time := (t_final - t_inicio)*24*60*60;
21 contador := contador + 1 ;
22
23 END LOOP;
24 /* test code - end */
25
26 dbms_output.put_line('Process End: ');
27 dbms_output.put_line(to_char(t_final,'yyyy-mm-dd hh24:mi:ss')) ;
28 dbms_output.put_line(' ');
29 dbms_output.put_line('------------------------------------------- ');
30 dbms_output.put_line('Summary: ');
31 dbms_output.put_line('Elapsed Time: '|| round(elapsed_time)) ;
32 dbms_output.put_line('Count#: '|| contador) ;
33 dbms_output.put_line(' ');
34 dbms_output.put_line('------------------------------------------- ');
35
36 EXCEPTION
37 WHEN OTHERS THEN
38 dbms_output.put_line('------------------------------------------- ');
39 dbms_output.put_line('Errors during execution.. ');
40 dbms_output.put_line('------------------------------------------- ');
41
42 ROLLBACK;
43 END;
44 /
Procedure created.
The Z_TEST program is a CPU intensive PL/SQL – procedure with little or no I/O. The test is done by running one session of the program, with a duration of 20 seconds. This loads the CPU close to 100%.
Execute the code and monitor system load.
SQL> CONNECT test/test
Connected.
SQL> SET TIMING ON
SQL> SET SERVEROUTPUT ON
SQL> execute z_test
executing z_test ...
Process Start:
2014-04-26 21:35:55
Process End:
2014-04-26 21:36:16
-------------------------------------------
Summary:
Elapsed Time: 21
Count#: 4476654
-------------------------------------------
PL/SQL procedure successfully completed.
Elapsed: 00:00:20.19
In a Linux environment, you can monitor system load executing the “top -c” command.
Tasks: 217 total, 2 running, 215 sleeping, 0 stopped, 0 zombie
Cpu(s): 95.0%us, 5.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 4208812k total, 4159116k used, 49696k free, 33152k buffers
Swap: 3145724k total, 2960k used, 3142764k free, 3098520k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
11159 oracle 20 0 1047m 58m 54m R 92.4 1.4 1:47.37 oracledb01
For this execution CPU load was almost 95%.
Now we will perform “CPU CAPPING” for “TEST” user.
Using an administrator account assign “TEST” user to “Z_TEST_APPL” consumer group and set this group as the initial consumer group. Perform this operation as follows:
SQL> BEGIN
2 dbms_resource_manager_privs.grant_switch_consumer_group(
3 grantee_name => 'TEST',
4 consumer_group => 'Z_TEST_APPL',
5 grant_option => FALSE
6 );
7 END;
8 /
PL/SQL procedure successfully completed.
SQL> BEGIN
2 dbms_resource_manager.set_initial_consumer_group(
3 user => 'TEST',
4 consumer_group => 'Z_TEST_APPL'
5 );
6 END;
7 /
PL/SQL procedure successfully completed.
Connect again with “TEST” user and verify the name of the session’s current resource consumer group.
SQL> SELECT username, resource_consumer_group
2 FROM v$session
3 WHERE username = 'TEST';
USERNAME RESOURCE_CONSUMER_GROUP
------------------------------ --------------------------------
TEST Z_TEST_APPL
Force “CPU CAPPING” by updating Z_DEFAULT_PLAN directives. Update Z_TEST_APPL to use only 30% of available CPU.
SQL> EXEC dbms_resource_manager.create_pending_area;
PL/SQL procedure successfully completed.
SQL> BEGIN
2 dbms_resource_manager.update_plan_directive(
3 'Z_DEFAULT_PLAN', 'Z_TEST_APPL', NEW_MAX_UTILIZATION_LIMIT=>30);
4 END;
5 /
PL/SQL procedure successfully completed.
SQL> EXEC dbms_resource_manager.validate_pending_area;
PL/SQL procedure successfully completed.
SQL> EXEC dbms_resource_manager.submit_pending_area;
PL/SQL procedure successfully completed.
As “TEST” database user execute the sample code again:
SQL> execute z_test
executing z_test ...
Process Start:
2014-04-26 21:45:55
Process End:
2014-04-26 21:46:16
-------------------------------------------
Summary:
Elapsed Time: 20
Count#: 4476754
-------------------------------------------
PL/SQL procedure successfully completed.
Elapsed: 00:00:20.53
And monitor CPU usage:
Tasks: 226 total, 1 running, 225 sleeping, 0 stopped, 0 zombie
Cpu(s): 29.2%us, 4.9%sy, 0.0%ni, 65.9%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 4208812k total, 3346332k used, 862480k free, 104092k buffers
Swap: 3145724k total, 0k used, 3145724k free, 2222028k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
14532 oracle 20 0 1045m 27m 25m S 29.5 0.7 0:10.08 oracledb01
For this execution CPU load was only 30%.
Oracle’s Database Resource Manager is no compensation for a poorly tuned system, but given an overloaded system, it provides the DBA the ability to manage the total amount of available processing resources amongst concurrent user sessions or groups of user sessions based on importance.
Link to script that contains the examples in this post.