Performance Instrumentation for PL/SQL: When, Why, How

5,128 views
4,929 views

Published on

Performance instrumentation is a little extra code that developers put into their PL/SQL applications that tells everyone—owners, users, system managers, and the software developers themselves—exactly where your software is spending your time. With it, managing performance is a snap. Good instrumentation makes it so normal people, not just specialists, can diagnose and solve performance problems quickly and permanently, often before your users even sense something is wrong. However, without good time-based performance instrumentation, managing performance becomes nightmarishly complex and expensive.

With as little as two lines of code you will be able to monitor specific tasks in your application and make one of the most difficult steps of implementing response-time based problem diagnosis (Method R) into one of the easiest. In addition, these techniques will enable you to correlate database statistics back to business tasks and help discover those tasks that are heavy resource consumers. This presentation will provide examples of how to perform the instrumentation using Oracle's built-in packages and a free open source instrumentation package called the Instrumentation Library for Oracle (ILO). Its cost on every level is free, and the significant collateral benefits that can be achieved will make code instrumentation part of your coding standards.

Published in: Technology, Business
0 Comments
9 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
5,128
On SlideShare
0
From Embeds
0
Number of Embeds
118
Actions
Shares
0
Downloads
415
Comments
0
Likes
9
Embeds 0
No embeds

No notes for slide
  • Course or presentation name © 2008 Method R Corp.
  • Collect properly scoped , un-aggregated profile data for each task while the task is exhibiting the behavior you want to record Login Triggers Unique code changes
  • Collect properly scoped , un-aggregated profile data for each task while the task is exhibiting the behavior you want to record Login Triggers Unique code changes
  • … costs you money
  • Your slow stuff will clog up even your fast stuff.
  • “ Slow. Why?” Ok …What does “slow” mean?
  • 129.98 seconds Why?
  • 129.98 seconds (this is R data) Why? Where is the time spent? (we need profile data)
  • Real-life performance instrumentation
  • Real-life performance instrumentation
  • Real-life performance instrumentation
  • Test 1: I delivered the presentation to my cats. I used a stop watch to keep a running time My cats were thrilled to participate My test presentation was just short of 2 hours
  • Emit a line-by-line execution of each step with a time stamp Available in any environment (e.g. development, production…) Always ready to be activated Easy to perform Light weight Uses built-in functionality as much as possible
  • Enterprise Manager V$ views
  • No idea of who are the clients Large amount of activity by unnamed modules and actions
  • Know who the client is and be able to drilldown See specific module and action that are the “Top Consumers” Able to trace right from DBConsole and Grid Control
  • Enterprise Manager V$ views
  • Enterprise Manager V$ views
  • Emit a line-by-line execution of each step with a time stamp Available in any environment (e.g. development, production…) Always ready to be activated Easy to perform Light weight Uses built-in functionality as much as possible
  • Create a simple logon trigger to set CLIENT_IDENTIFIER CREATE OR REPLACE TRIGGER client_id_logon_trg AFTER LOGON ON DATABASE DECLARE my_service SYS.V_$SESSION.SERVICE_NAME%TYPE; my_clientid SYS.V_$SESSION.CLIENT_IDENTIFIER%TYPE; my_ip_address SYS.V_$SESSION.TERMINAL%TYPE; my_os_user SYS.V_$SESSION.OSUSER%TYPE; my_audsid SYS.V_$SESSION.AUDSID%TYPE; my_program SYS.V_$SESSION.PROGRAM%TYPE; CLIENT_ID_DELIM CHAR(1) := '~'; BEGIN IF USER NOT IN ('SYS') AND USER IS NOT NULL THEN my_clientid := SYS_CONTEXT('USERENV', 'CLIENT_IDENTIFIER'); IF my_clientid IS NULL THEN my_service := SYS_CONTEXT('USERENV', 'SERVICE_NAME'); my_ip_address := NVL(SYS_CONTEXT('USERENV', 'IP_ADDRESS') ,SYS_CONTEXT('USERENV', 'TERMINAL')); my_os_user := SYS_CONTEXT('USERENV', 'OS_USER'); my_audsid := TO_NUMBER(SYS_CONTEXT('USERENV', 'SESSIONID')); SELECT PROGRAM INTO my_program FROM SYS.V_$SESSION WHERE AUDSID = my_audsid AND ROWNUM = 1; DBMS_SESSION.SET_IDENTIFIER(my_os_user || CLIENT_ID_DELIM || my_ip_address || CLIENT_ID_DELIM || my_program || CLIENT_ID_DELIM || my_service); END IF; END IF; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('client_id_logon_trg: Exception thrown'); END client_id_logon_trg;
  • select column_name, table_name from dba_tab_cols where column_name like 'CLIENT_ID%' order by table_name COLUMN_NAME TABLE_NAME ------------------------------ ------------------------------ CLIENT_ID ALL_SCHEDULER_JOBS CLIENT_ID ALL_SCHEDULER_JOB_LOG CLIENT_ID ALL_SCHEDULER_WINDOW_LOG CLIENT_ID DBA_AUDIT_EXISTS CLIENT_ID DBA_AUDIT_OBJECT CLIENT_ID DBA_AUDIT_SESSION CLIENT_ID DBA_AUDIT_STATEMENT CLIENT_ID DBA_AUDIT_TRAIL CLIENT_ID DBA_COMMON_AUDIT_TRAIL CLIENT_ID DBA_FGA_AUDIT_TRAIL CLIENT_ID DBA_HIST_ACTIVE_SESS_HISTORY CLIENT_ID DBA_SCHEDULER_JOBS CLIENT_ID DBA_SCHEDULER_JOB_LOG CLIENT_ID DBA_SCHEDULER_WINDOW_LOG CLIENT_IDENTIFIER GLOBAL_CONTEXT CLIENT_ID GV_$ACTIVE_SESSION_HISTORY CLIENT_IDENTIFIER GV_$CLIENT_STATS CLIENT_IDENTIFIER GV_$GLOBALCONTEXT CLIENT_IDENTIFIER GV_$SESSION CLIENT_ID KET$_CLIENT_CONFIG CLIENT_ID KET$_CLIENT_TASKS CLIENT_IDENTIFIER MGMT_USER_CONTEXT CLIENT_ID SCHEDULER$_EVENT_LOG CLIENT_ID SCHEDULER$_JOB CLIENT_ID SCHEDULER$_LIGHTWEIGHT_JOB CLIENT_ID USER_AUDIT_OBJECT CLIENT_ID USER_AUDIT_SESSION CLIENT_ID USER_AUDIT_STATEMENT CLIENT_ID USER_AUDIT_TRAIL CLIENT_ID USER_SCHEDULER_JOBS CLIENT_ID USER_SCHEDULER_JOB_LOG CLIENT_ID V_$ACTIVE_SESSION_HISTORY CLIENT_IDENTIFIER V_$CLIENT_STATS CLIENT_IDENTIFIER V_$GLOBALCONTEXT CLIENT_IDENTIFIER V_$SESSION CLIENT_ID WRH$_ACTIVE_SESSION_HISTORY CLIENT_ID WRH$_ACTIVE_SESSION_HISTORY_BL 37 rows selected.
  • Valid values of dest parameter are 1 = Trace file, 2 = Alert log, 3 = Both
  • Monitor sessions by querying v$session
  • Valid values of dest parameter are 1 = Trace file, 2 = Alert log, 3 = Both
  • Monitor sessions by querying v$session
  • http://sourceforge.net/projects/hotsos-ilo/
  • Turning on trace is usually a run-time decision ( DBMS_MONITOR ) The developer will simply include BEGIN_TASK ILO calls that will check to see if someone has requested that a trace be initiated For development testing, the developer simply calls SET_MARK_ALL_TASKS_INTERESTING (TRUE, TRUE) to express their intent to trace Calls to this method will not typically be present in production code Except perhaps via a menu option (Help > Debug > Trace)
  • Performance Instrumentation for PL/SQL: When, Why, How

    1. 1. Performance Instrumentation for PL/SQL When, Why, How Karen Morton
    2. 2. Your speaker… <ul><li>Karen Morton </li></ul><ul><ul><li>Sr. Principal Database Engineer </li></ul></ul><ul><ul><li>Educator, DBA, developer, consultant, researcher, author, speaker, … </li></ul></ul><ul><li>Come see me… </li></ul><ul><ul><li>karenmorton.blogspot.com </li></ul></ul><ul><ul><li>An Oracle user group near you </li></ul></ul>
    3. 3. <ul><li>Why guess? </li></ul><ul><li>When you can know . </li></ul>
    4. 4. <ul><li>Method R. </li></ul><ul><li>“ R” stands for </li></ul><ul><li>response time . </li></ul>
    5. 5. <ul><li>Target the </li></ul><ul><li>right task </li></ul>1
    6. 6. <ul><li>Collect its </li></ul><ul><li>R </li></ul><ul><li>Details </li></ul>2
    7. 7. <ul><li>Forecast, act </li></ul>3
    8. 8. <ul><li>Stop when cost of </li></ul><ul><li>additional repairs exceeds </li></ul><ul><li>cost of the problem </li></ul>
    9. 9. <ul><li>Go to Step 1 </li></ul>4
    10. 10. <ul><li>The hardest part is </li></ul><ul><li>getting the “right” </li></ul><ul><li>information </li></ul>
    11. 11. <ul><li>Collecting properly scoped, </li></ul><ul><li>Un-aggregated profile data </li></ul>
    12. 12. <ul><li>If you can’t measure it, you can’t manage it. </li></ul><ul><li>― David Garvin </li></ul>
    13. 13. <ul><li>There are two types of performance problems in this world... </li></ul>
    14. 14. <ul><li>1 </li></ul><ul><li>Response time problems. </li></ul>
    15. 15. <ul><li>2 </li></ul><ul><li>Inefficiencies that aren’t response time problems. </li></ul><ul><li>Yet. </li></ul>
    16. 16. <ul><li>Therefore... </li></ul>
    17. 17. <ul><li>You must be able to attack response time problems for specific tasks that the business cares about. </li></ul>
    18. 18. <ul><li>Example... </li></ul>
    19. 19. <ul><li>Posting hurts. </li></ul><ul><li>Fix it. </li></ul>
    20. 20. <ul><li>Why should you care? </li></ul>
    21. 22. <ul><li>You need to be able to attack inefficiencies that aren’t yet noticeable as user response time problems. </li></ul>
    22. 23. <ul><li>Example... </li></ul>
    23. 24. <ul><li>Posting takes 3 hours. </li></ul><ul><li>It should take 2, but no user really cares. </li></ul>
    24. 25. <ul><li>Why should *you* care? </li></ul>
    25. 26. <ul><li>Because </li></ul><ul><li>costs you money </li></ul>waste
    26. 27. TCO $$ Waste Labor $$ Hardware $$ Software $$
    27. 28. <ul><li>And waste... </li></ul>
    28. 29. <ul><li>...makes other work go slower… </li></ul>
    29. 30. <ul><li>...even your fast stuff </li></ul>
    30. 31. <ul><li>recap... </li></ul>
    31. 32. <ul><li>You must be able to attack </li></ul><ul><li>1. Response time problems </li></ul><ul><li>2. Efficiency problems </li></ul>
    32. 33. <ul><li>Here’s where </li></ul><ul><li>instrumentation </li></ul><ul><li>comes in </li></ul>
    33. 34. Why is this program slow? <ul><li>SQL> exec p </li></ul><ul><li>PL/SQL procedure successfully completed. </li></ul><ul><li>SQL> </li></ul>
    34. 35. What is “slow”? <ul><li>SQL> set timing on </li></ul><ul><li>SQL> exec p </li></ul><ul><li>PL/SQL procedure successfully completed. </li></ul><ul><li>Elapsed 00:02:09:98 </li></ul><ul><li>SQL> </li></ul>
    35. 36. So we open up our code. <ul><li>create or replace procedure p </li></ul><ul><li>as </li></ul><ul><li>begin </li></ul><ul><li>q; </li></ul><ul><li>r; </li></ul><ul><li>s; </li></ul><ul><li>end; </li></ul><ul><li>/ </li></ul>
    36. 37. Let’s find out. <ul><li>create or replace procedure p as </li></ul><ul><li>t0 number; </li></ul><ul><li>t1 number; </li></ul><ul><li>t2 number; </li></ul><ul><li>t3 number; </li></ul><ul><li>begin </li></ul><ul><li>t0 := dbms_utility.get_time; </li></ul><ul><li>q; </li></ul><ul><li>t1 := dbms_utility.get_time ; </li></ul><ul><li>dbms_output.put_line ('Procedure q: ' || to_char((t1 - t0)/100)); </li></ul><ul><li>r; </li></ul><ul><li>t2 := dbms_utility.get_time ; </li></ul><ul><li>dbms_output.put_line ('Procedure r: ' || to_char((t2 - t1)/100)); </li></ul><ul><li>s; </li></ul><ul><li>t3 := dbms_utility.get_time ; </li></ul><ul><li>dbms_output.put_line ('Procedure s: ' || to_char((t3 - t2)/100)); </li></ul><ul><li>dbms_output.put_line ('Total R : ' || to_char((t3 - t0)/100)); </li></ul><ul><li>end; </li></ul><ul><li>/ </li></ul>
    37. 38. So now we know. <ul><li>SQL> set timing on </li></ul><ul><li>SQL> exec p </li></ul><ul><li>Procedure q: 1 </li></ul><ul><li>Procedure r: 114 </li></ul><ul><li>Procedure s: 15 </li></ul><ul><li>Total R : 130 </li></ul><ul><li>Elapsed 00:02:09:99 </li></ul><ul><li>SQL> </li></ul>
    38. 39. <ul><li>What was the co $ t? </li></ul>
    39. 40. <ul><li>Response time increased </li></ul><ul><li>by .01 seconds </li></ul><ul><li>(From 129.98 to 129.99) </li></ul>
    40. 41. <ul><li>Code additions </li></ul><ul><li>4 variable declarations </li></ul><ul><li>8 lines of code </li></ul>
    41. 42. <ul><li>These new lines </li></ul><ul><li>of code are called performance instrumentation . </li></ul>
    42. 43. <ul><li>With this data, </li></ul><ul><li>we know where </li></ul><ul><li>to focus our attention. </li></ul>
    43. 44. <ul><li>Where would you start </li></ul><ul><li>if you didn’t have this data? </li></ul>
    44. 45. <ul><li>What would happen if </li></ul><ul><li>you started work on </li></ul><ul><li>procedure Q or S ? </li></ul>Procedure q: 1 Procedure r: 114 Procedure s: 15 Total R : 130
    45. 46. <ul><li>Why guess? </li></ul><ul><li>When you can know . </li></ul>
    46. 47. <ul><li>Profiling is a </li></ul><ul><li>requirement of good </li></ul><ul><li>development hygiene </li></ul>
    47. 48. <ul><li>It makes your apps </li></ul><ul><li>faster and cheaper </li></ul>
    48. 49. <ul><li>Without profiling… </li></ul><ul><li>Can’t tell where time goes </li></ul><ul><li>“ Tune” everything you can </li></ul><ul><li>Learn about everything possible </li></ul><ul><li>“ Tuning” continues even when improvement is impossible </li></ul><ul><li>With profiling… </li></ul><ul><li>Know where code spends time </li></ul><ul><li>Optimize only relevant code path </li></ul><ul><li>Learn first in high-impact areas </li></ul><ul><li>“ Tuning” ceases when objective is achieved </li></ul>
    49. 50. <ul><li>Performance </li></ul><ul><li>instrumentation </li></ul><ul><li>in real life </li></ul>
    50. 51. <ul><li>I just started a new job </li></ul><ul><li>and need to drive 15 miles from home to the office each day. </li></ul>
    51. 52. <ul><li>I decide to leave home at </li></ul><ul><li>7:40am expecting to be </li></ul><ul><li>there by 8:00am. </li></ul>
    52. 53. Day 1 Depart 7:40am Arrive 8:20am
    53. 54. <ul><li>Total Drive Time </li></ul><ul><li>40 minutes </li></ul>
    54. 55. <ul><li>Argh! </li></ul><ul><li>It’s not good to be </li></ul><ul><li>late for your first </li></ul><ul><li>day on a new job! </li></ul>
    55. 56. <ul><li>What am I going to do? </li></ul>
    56. 57. <ul><li>First, let me find out how my drive time was spent. </li></ul>
    57. 58. Category Miles Elapsed Time (minutes) Neighborhood 1 3 Burke Centre Pkwy 2.5 8 Fairfax County Pkwy 6 12 I-66 2.5 8 Hwy 28 2 5 Westfields Blvd to Office 1.5 4 Total 15.5 40 minutes
    58. 59. <ul><li>Try another route? </li></ul>
    59. 60. <ul><li>Buy a faster car? </li></ul>
    60. 61. <ul><li>Hire private air transport? </li></ul>
    61. 62. Conclusion Leave earlier to allow for traffic fluctuations
    62. 63. <ul><li>Why guess? </li></ul><ul><li>When you can know . </li></ul>
    63. 64. <ul><li>What is instrumentation </li></ul><ul><li>and why is it important? </li></ul>
    64. 65. <ul><li>Measures the </li></ul><ul><li>attributes of a system </li></ul>
    65. 66. Creates monitoring mechanisms
    66. 67. Tracks and measures performance
    67. 68. <ul><li>What are the objectives </li></ul><ul><li>of proper instrumentation? </li></ul>
    68. 69. <ul><li>Easy to </li></ul><ul><li>activate </li></ul>
    69. 70. <ul><li>Capture timings of </li></ul><ul><li>business-critical </li></ul><ul><li>tasks </li></ul>
    70. 71. <ul><li>Lightweight </li></ul>
    71. 72. <ul><li>Leverages </li></ul><ul><li>built-in functionality </li></ul>
    72. 73. What are the benefits of proper instrumentation?
    73. 74. <ul><li>Appropriately </li></ul><ul><li>scoped trace </li></ul><ul><li>information </li></ul>
    74. 75. <ul><li>More meaningful </li></ul><ul><li>information </li></ul>
    75. 76. This?
    76. 77. Or this?
    77. 78. This?
    78. 79. Or this?
    79. 80. <ul><li>Why did this take so long? </li></ul><ul><li>What would happen if…? </li></ul><ul><li>Is this thing efficient? </li></ul><ul><li>Am I done yet? </li></ul>Easily answer questions like:
    80. 81. <ul><li>Provide final word </li></ul><ul><li>on disputes </li></ul>
    81. 82. How do I instrument my code?
    82. 83. <ul><li>Start with </li></ul><ul><li>supplied packages </li></ul>
    83. 84. <ul><li>DBMS_SESSION </li></ul>
    84. 85. <ul><li>set_identifier </li></ul><ul><li>identifies current </li></ul><ul><li>session to make </li></ul><ul><li>tracing easier </li></ul>
    85. 86. Lets instance know which end users are on which connection
    86. 87. <ul><li>DBMS_SESSION.set_identifier </li></ul><ul><li>(client_id =>'jqpublic~ora11r1') </li></ul>
    87. 88. <ul><li>LOGON Trigger </li></ul><ul><ul><ul><li>SYS_CONTEXT('USERENV', 'CLIENT_IDENTIFIER') </li></ul></ul></ul><ul><ul><ul><li>SYS_CONTEXT('USERENV', 'SERVICE_NAME') </li></ul></ul></ul><ul><ul><ul><li>SYS_CONTEXT('USERENV', 'IP_ADDRESS') </li></ul></ul></ul><ul><ul><ul><li>SYS_CONTEXT('USERENV', 'TERMINAL') </li></ul></ul></ul><ul><ul><ul><li>SYS_CONTEXT('USERENV', 'OS_USER') </li></ul></ul></ul><ul><ul><ul><li>SYS_CONTEXT('USERENV', 'SESSIONID') </li></ul></ul></ul>
    88. 89. <ul><li>SELECT client_identifier,… </li></ul><ul><li>FROM V$SESSION </li></ul><ul><li>… plus almost 40 other views </li></ul>
    89. 90. <ul><li>DBMS_SYSTEM </li></ul>
    90. 91. <ul><li>ksdddt </li></ul><ul><li>writes date/time stamp </li></ul><ul><li>ksdwrt </li></ul><ul><li>writes any message </li></ul>
    91. 92. <ul><li>DBMS_SYSTEM.ksdddt </li></ul><ul><ul><li>*** 2008-10-02 15:36:51.314 </li></ul></ul><ul><li>DBMS_SYSTEM.ksdwrt </li></ul><ul><li>(dest=>1, ' Here I am! ' ) </li></ul><ul><ul><li>Here I am! </li></ul></ul>
    92. 93. <ul><li>DBMS_APPLICATION_INFO </li></ul>
    93. 94. <ul><li>set_module </li></ul><ul><li>register business tasks </li></ul><ul><li>and related logical </li></ul><ul><li>units of work </li></ul>
    94. 95. <ul><li>read_module </li></ul><ul><li>determine current </li></ul><ul><li>business task and </li></ul><ul><li>logical unit of work </li></ul>
    95. 96. <ul><li>set_session_longops </li></ul><ul><li>monitor progress </li></ul><ul><li>of long-running </li></ul><ul><li>operations </li></ul>
    96. 97. <ul><li>DBMS_APPLICATION_INFO. </li></ul><ul><li>set_module( </li></ul><ul><li>module_name=> ' Order Entry ' , </li></ul><ul><li>action_name=> ' Get Order Items ' ) </li></ul>
    97. 98. <ul><li>SELECT module, action, … </li></ul><ul><li>FROM V$SESSION </li></ul><ul><li>– or – </li></ul><ul><li>FROM V$SESSION_LONGOPS </li></ul><ul><li>… plus almost 40 other views </li></ul>
    98. 99. <ul><li>DBMS_MONITOR </li></ul>
    99. 100. <ul><li>client_id_trace_enable </li></ul><ul><li>database_trace_enable </li></ul><ul><li>serv_mod_act_trace_enable </li></ul><ul><li>session_trace_enable </li></ul><ul><li>start extended </li></ul><ul><li>SQL tracing </li></ul>
    100. 101. <ul><li>DBMS_MONITOR. </li></ul><ul><li>serv_mod_act_trace_enable( </li></ul><ul><li>service_name=> ' ora11r1 ' , </li></ul><ul><li>module_name=> ' Order Entry ' , </li></ul><ul><li>action_name=> ' Get Order Items ' ) </li></ul>
    101. 102. <ul><li>Trace file will contain </li></ul><ul><li>*** ACTION NAME:(Get Order Items) </li></ul><ul><li>2009-08-02 01:48:56.573 </li></ul><ul><li>*** MODULE NAME:(Order Entry) </li></ul><ul><li>2009-08-02 01:48:56.573 </li></ul>
    102. 103. <ul><li>SELECT * </li></ul><ul><li>FROM DBA_ENABLED_TRACES </li></ul><ul><ul><ul><li>TRACE_TYPE SERVICE_MODULE_ACTION </li></ul></ul></ul><ul><ul><ul><li>PRIMARY_ID ora11r1 </li></ul></ul></ul><ul><ul><ul><li>QUALIFIER_ID1 Order Entry </li></ul></ul></ul><ul><ul><ul><li>QUALIFIER_ID2 Get Order Items </li></ul></ul></ul><ul><ul><ul><li>WAITS TRUE </li></ul></ul></ul><ul><ul><ul><li>BINDS TRUE </li></ul></ul></ul><ul><ul><ul><li>PLAN_STATS FIRST_EXEC </li></ul></ul></ul><ul><ul><ul><li>INSTANCE_NAME <null> </li></ul></ul></ul>
    103. 104. <ul><li>client_id_stat_enable </li></ul><ul><li>serv_mod_act_stat_enable </li></ul><ul><li>gather performance </li></ul><ul><li>metrics </li></ul>
    104. 105. <ul><li>DBMS_MONITOR. </li></ul><ul><li>client_id_stat_enable </li></ul><ul><li>(client_id =>'jqpublic~ora11r1') </li></ul>
    105. 106. <ul><li>CLIENT_IDENTIFIER STAT_NAME TIME_SECS </li></ul><ul><li>----------------- --------------------------- ---------- </li></ul><ul><li>jqpublic~ora11r1 DB CPU .009 </li></ul><ul><li>jqpublic~ora11r1 DB time .009 </li></ul><ul><li>jqpublic~ora11r1 sql execute elapsed time .007 </li></ul><ul><li>jqpublic~ora11r1 parse time elapsed .001 </li></ul><ul><li>. . . </li></ul>SELECT * FROM V$CLIENT_STATS
    106. 107. SELECT * FROM V$SERV_MOD_ACT_STATS when using serv_mod_act_stat_enable
    107. 108. Where should I place instrumentation?
    108. 109. <ul><li>Set module & action </li></ul><ul><li>below the </li></ul><ul><li>BEGIN statement </li></ul>
    109. 110. <ul><li>Update module & action </li></ul><ul><li>for any new </li></ul><ul><li>business tasks </li></ul>
    110. 111. <ul><li>Place above all </li></ul><ul><li>END and RETURN </li></ul><ul><li>statements </li></ul><ul><li>(set to null) </li></ul>
    111. 112. <ul><li>Place inside all </li></ul><ul><li>EXCEPTION </li></ul><ul><li>handlers </li></ul><ul><li>(set to null) </li></ul>
    112. 113. <ul><li>Avoid placing </li></ul><ul><li>calls inside </li></ul><ul><li>LOOPs </li></ul>
    113. 114. <ul><li>Example... </li></ul>
    114. 115. PROCEDURE get_emp_simple_instr IS fnlist_stack fnlist_tab; lnlist_stack lnlist_tab; BEGIN DBMS_APPLICATION_INFO.set_module(module_name => 'Human Resources’,action_name => 'Get Employees'); SELECT first_name, last_name BULK COLLECT INTO fnlist_stack, lnlist_stack FROM employees; DBMS_APPLICATION_INFO.set_module(NULL, NULL); EXCEPTION WHEN OTHERS THEN DBMS_APPLICATION_INFO.set_module(NULL, NULL); DBMS_OUTPUT.PUT_LINE('get_emp_simple_instr => ERROR'); END get_emp_simple_instr;
    115. 116. 08:00:00 MODULE = ‘Human resources’ ACTION= ‘get employees’ 08:02:04 MODULE = null ACTION = null
    116. 117. PROCEDURE get_emp_jobs_instr_flawed IS jtlist_stack jtlist_tab; lnlist_stack lnlist_tab; BEGIN DBMS_APPLICATION_INFO.set_module(module_name => 'Human Resources', action_name => 'Get Employees and Jobs'); get_emp_simple_instr; SELECT last_name, job_title BULK COLLECT INTO lnlist_stack, jtlist_stack FROM employees e, jobs j WHERE e.job_id = j.job_id; DBMS_APPLICATION_INFO.set_module(NULL, NULL); EXCEPTION WHEN OTHERS THEN DBMS_APPLICATION_INFO.set_module(NULL, NULL); DBMS_OUTPUT.PUT_LINE('get_emp_jobs_instr_flawed => ERROR'); END get_emp_jobs_instr_bad;
    117. 118. 08:10:00 MODULE = ‘Human resources’ ACTION = ‘get employees and jobs’ 08:12:04 MODULE = null ACTION = null 08:10:01 MODULE = ‘Human resources’ ACTION = ‘get employees’ 08:13:32 <end>
    118. 119. <ul><li>Problems can occur </li></ul><ul><li>when one similarly </li></ul><ul><li>instrumented procedure </li></ul><ul><li>calls another </li></ul>
    119. 120. <ul><li>Remember to </li></ul><ul><li>store module & action </li></ul><ul><li>in variables </li></ul><ul><li>and “reset” as needed </li></ul><ul><li>throughout code </li></ul>
    120. 121. PROCEDURE get_emp_instr_good IS fnlist_stack fnlist_tab; lnlist_stack lnlist_tab; preModuleName VARCHAR2(48) := NULL; preActionName VARCHAR2(32) := NULL; BEGIN DBMS_APPLICATION_INFO.read_module( module_name => preModuleName, action_name => preActionName); DBMS_APPLICATION_INFO.set_module( module_name => 'Human Resources', action_name => 'Get Employees'); SELECT first_name, last_name BULK COLLECT INTO fnlist_stack, lnlist_stack FROM employees; DBMS_APPLICATION_INFO.set_module( module_name => preModuleName, action_name => preActionName); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('HR_Package.get_emp_instr_good ERROR'); DBMS_APPLICATION_INFO.set_module( module_name => preModuleName, action_name => preActionName); END get_emp_instr_good;
    121. 122. <ul><li>Instrumentation </li></ul><ul><li>Library for Oracle </li></ul><ul><li>( ILO ) </li></ul>
    122. 123. <ul><li>Used to simplify the </li></ul><ul><li>process of instrumenting </li></ul><ul><li>your code </li></ul>
    123. 124. <ul><li>3 packages </li></ul><ul><li>ILO_TASK </li></ul><ul><li>ILO_TIMER </li></ul><ul><li>ILO_SYSUTIL </li></ul>
    124. 125. <ul><li>Requires </li></ul><ul><li>Oracle version </li></ul><ul><li>9.2.0.1 </li></ul><ul><li>or above </li></ul>
    125. 126. <ul><li>Makes </li></ul><ul><li>instrumenting </li></ul><ul><li>code </li></ul><ul><li>easy </li></ul>
    126. 127. <ul><li>Encapsulates & simplifies </li></ul><ul><li>the use of </li></ul><ul><li>dbms_application_info </li></ul><ul><li>and </li></ul><ul><li>dbms_session </li></ul>
    127. 128. <ul><li>Download from </li></ul><ul><li>SourceForge.net </li></ul>Open Source !
    128. 129. <ul><li>Can be modified to </li></ul><ul><li>meet your needs </li></ul>
    129. 130. <ul><li>Place 1 st call </li></ul><ul><li>below the </li></ul><ul><li>BEGIN statement </li></ul>
    130. 131. <ul><li>ILO_TASK.begin_task( </li></ul><ul><li>module_name=> ' Human Resources ' , </li></ul><ul><li>action_name=> ' Get Employees ' ) </li></ul>
    131. 132. <ul><li>Change for any new </li></ul><ul><li>business tasks </li></ul>
    132. 133. <ul><li>ILO_TASK.begin_task( </li></ul><ul><li>module_name=> ' Human Resources ' , </li></ul><ul><li>action_name=> ' Get Jobs ' ) </li></ul>
    133. 134. <ul><li>Place end calls </li></ul><ul><li>above all </li></ul><ul><li>END and RETURN </li></ul><ul><li>statements </li></ul>
    134. 135. <ul><li>and inside all </li></ul><ul><li>EXCEPTION </li></ul><ul><li>handlers </li></ul>
    135. 136. <ul><li>ILO_TASK.end_task </li></ul>
    136. 137. <ul><li>That’s </li></ul><ul><li>it! </li></ul>
    137. 138. PROCEDURE get_emp_instr_better IS fnlist_stack fnlist_tab; lnlist_stack lnlist_tab; BEGIN ILO_TASK.BEGIN_TASK(module_name => 'Human Resources' ,action_name => 'Get Employees'); SELECT first_name, last_name BULK COLLECT INTO fnlist_stack, lnlist_stack FROM employees; ILO_TASK.END_TASK; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('get_emp_instr_better ERROR'); ILO_TASK.END_TASK; END get_emp_instr_better;
    138. 139. <ul><li>Turning on trace </li></ul><ul><li>using ILO </li></ul>
    139. 140. <ul><li>Activating trace is a </li></ul><ul><li>run-time decision </li></ul>
    140. 141. <ul><li>The developer adds </li></ul><ul><li>BEGIN_TASK & END_TASK </li></ul><ul><li>calls to the code </li></ul>
    141. 142. <ul><li>The DBA starts </li></ul><ul><li>tracing with </li></ul><ul><li>DBMS_MONITOR </li></ul>
    142. 143. <ul><li>The developer can start </li></ul><ul><li>tracing with ilo_task </li></ul><ul><li>SET_MARK_ALL_TASKS_INTERESTING </li></ul><ul><li>(TRUE, TRUE) </li></ul>
    143. 144. <ul><li>Case </li></ul><ul><li>study </li></ul>
    144. 145. <ul><li>The Problem </li></ul>
    145. 146. <ul><li>Business critical task </li></ul><ul><li>taking 40 seconds </li></ul>
    146. 147. <ul><li>MAX tolerated </li></ul><ul><li>execution time </li></ul><ul><li>15 seconds </li></ul>
    147. 148. <ul><li>Weeks spent searching for root cause and fix </li></ul>
    148. 149. <ul><li>Task was a single </li></ul><ul><li>PL/SQL package </li></ul><ul><li>with 2,300 lines </li></ul><ul><li>of code </li></ul>
    149. 150. <ul><li>Code was executed </li></ul><ul><li>over 100 times </li></ul><ul><li>per hour </li></ul>
    150. 151. <ul><li>Running on </li></ul><ul><li>multi-node RAC </li></ul>
    151. 152. <ul><li>Trace collection not </li></ul><ul><li>very helpful due to </li></ul><ul><li>improper scoping </li></ul>
    152. 153. <ul><li>Needed instrumentation </li></ul><ul><li>to provide </li></ul><ul><li>proper scoping </li></ul>
    153. 154. <ul><li>Code contained </li></ul><ul><li>36 business tasks </li></ul><ul><li>all marked with </li></ul><ul><li>in-line comments </li></ul>
    154. 155. <ul><li>In-line comments </li></ul><ul><li>used to guide </li></ul><ul><li>instrumentation </li></ul><ul><li>with ILO </li></ul>
    155. 156. <ul><li>Spent </li></ul><ul><li>40 minutes </li></ul><ul><li>to instrument </li></ul><ul><li>36 tasks </li></ul>
    156. 157. <ul><li>Instrumented </li></ul><ul><li>code placed </li></ul><ul><li>into production </li></ul>
    157. 158. <ul><li>Tracing activated </li></ul><ul><li>using dbms_monitor </li></ul><ul><li>for the instrumented </li></ul><ul><li>module & actions </li></ul>
    158. 159. <ul><li>Problem </li></ul><ul><li>code </li></ul><ul><li>was executed </li></ul>
    159. 160. <ul><li>Tracing </li></ul><ul><li>deactivated </li></ul>
    160. 161. <ul><li>Trace file </li></ul><ul><li>retrieved </li></ul><ul><li>and profiled </li></ul>
    161. 162. Majority of time spent waiting for gc cr multi block request
    162. 163. Further drilldown showed one insert and one delete to be largest “R” contributors
    163. 164. Reviewed the insert statement which was actually inserting via a SELECT
    164. 165. 1) Noted excessive LIO 2) Plan showed use of full table scan
    165. 166. <ul><li>The Fix </li></ul>
    166. 167. Added index on ts_row_seq
    167. 168. <ul><li>Problem code was </li></ul><ul><li>executed and </li></ul><ul><li>traced again </li></ul>
    168. 169. New response time 10.118 seconds
    169. 170. <ul><li>Total time to </li></ul><ul><li>find and fix </li></ul><ul><li>the problem: </li></ul><ul><li>less than 1 hour </li></ul>
    170. 171. <ul><li>Why guess? </li></ul><ul><li>When you can know . </li></ul>
    171. 172. <ul><li>Summary </li></ul>
    172. 173. <ul><li>When should you consider </li></ul><ul><li>performance </li></ul><ul><li>instrumentation? </li></ul>
    173. 174. <ul><li>Any time there is code </li></ul><ul><li>whose performance </li></ul><ul><li>you might ever </li></ul><ul><li>care about. </li></ul>
    174. 175. <ul><li>Why should </li></ul><ul><li>performance </li></ul><ul><li>instrumentation </li></ul><ul><li>matter? </li></ul>
    175. 176. <ul><li>Because when it </li></ul><ul><li>isn’t in place, </li></ul><ul><li>managing performance </li></ul><ul><li>is too complex </li></ul><ul><li>and expensive. </li></ul>
    176. 177. <ul><li>How should </li></ul><ul><li>performance </li></ul><ul><li>instrumentation </li></ul><ul><li>be done? </li></ul>
    177. 178. <ul><li>By adding a few </li></ul><ul><li>extra lines of code </li></ul><ul><li>to register </li></ul><ul><li>each business task. </li></ul>
    178. 179. <ul><li>Performance </li></ul><ul><li>doesn’t need </li></ul><ul><li>to be hard </li></ul>
    179. 180. <ul><li>Let your software </li></ul><ul><li>help you! </li></ul>
    180. 181. <ul><li>It’s a mindless task </li></ul><ul><li>your computer is willing </li></ul><ul><li>to do for you… </li></ul>
    181. 182. <ul><li>… if you just </li></ul><ul><li>ask it to. </li></ul>
    182. 183. <ul><li>Why guess? </li></ul><ul><li>When you can know . </li></ul>
    183. 184. <ul><li>Thank you! </li></ul>
    184. 185. Questions & Answers

    ×