Imagine a car with no speedometer. There are speed limit signs and policemen all around with radar guns waiting to catch you speeding, but you have no way of knowing how fast you're going. Of course, a car like this has no openable hood (no bonnet), so to change the air filter, you have to hire a specialist to saw into the body of your car. A car like this would be preposterous. Yet people write software like this all the time.
The Oracle Database has some of the best performance logging features built into it of any software in the world. You can use it with any application—even applications that were built without logging and monitoring in mind. But you can go SO much further if you bother to include some performance logging features in your application. In this session, I explain Oracle's extended SQL tracing feature and describe how to enable and disable it. Then I show some innovative ideas that will help you design and build database applications that are easier to monitor, manage, and maintain throughout the software development life cycle.
Best VIP Call Girls Noida Sector 39 Call Me: 8448380779
Innovative Specifications for Better Performance Logging and Monitoring
1. @CaryMillsap
Innovative Specifications
for Better Performance
Logging and Monitoring
Cary Millsap
Cintra Software and Services · Method R Corporation
@CaryMillsap
#Kscope18
Walt Disney World Dolphin Resort, Orlando, Florida
9:00a–10:00a Tuesday 12 June 2018
1
2. 2@CaryMillsap
2020
2015
2010
2005
2000
1995
1990
1985
100 45
6
3
hotsos
Method R
TM
Optimal Flexible Architecture
Oracle APS
System Pe ormance Group
Method R Profiler
Method R Tools
Method R Trace
The definitive guide to accurate, high-precision
measurement of user performance experiences,
for Oracle application developers and database
administrators.
Cary V. Millsap
TM
MeTHOD R
TM
The Guide to
MASTERING
ORACLE
TRACE DATA
Second Edition
REVISED
UPDA
TED
NEW PA
G
ES
1 3 2
Method R Workbench
TRASIR
SimDiff
Cary Millsap
7. Hey, the TPS report is slow. It always
used to run in about 10 minutes, but
then it went to 20, and now it’s taking
over an hour.
Any idea why?
🤣 🤣 🤣 What kind of idea would I have?
It’s *your* code, bruh.
7@CaryMillsap
8. So, you stick some print statements into your code.
You recompile it.
You test it.
You commit it and push it.
You deploy it.
8@CaryMillsap
9. Still slow.
Here, I’ve pushed a new
executable. Try it now. When it’s
finished, email me the file called
$HOME/tps.log
Ok, check your mail.
Yeah, I know. But the log file will tell
me where it’s spending its time.
Just curious. Why didn’t it do the
thing with the log file to begin with?
●●●
9@CaryMillsap
10. @CaryMillsap
Homemade logging
What would those printf() statements look like?
function f(stuff) {
printf(LOG, "%s %s %sn", timestamp, "f{", stuff);
for record in (records) {
process(record);
}
printf(LOG, "%s %s %d recordsn", timestamp, "}", count(records));
}
Then you’ll need to parse the log to compute durations.
(Or change the code to print them.)
10
11. @CaryMillsap
Homemade logging
What would those printf() statements look like?
function f(stuff) {
printf(LOG, "%s %s %sn", timestamp, "f{", stuff);
for record in (records) {
process(record);
}
printf(LOG, "%s %s %d recordsn", timestamp, "}", count(records));
}
Maybe you’ll need more printf calls to cope with skew in iteration durations.
11
12. @CaryMillsap
1. package com.test;
2.
3. import org.apache.logging.log4j.Logger;
4. import org.apache.logging.log4j.LogManager;
5.
6. import java.util.Random;
7.
8. public class TestService {
9. private Logger logger = LogManager.getLogger(TestService.class.getName());
10.
11. private String[] messages = new String[] {
12. "Hello, World",
13. "Goodbye Cruel World",
14. "You had me at hello"
15. };
16. private Random rand = new Random(1);
17.
18. public void setMessages(String[] messages) {
19. logger.traceEntry(new JsonMessage(messages));
20. this.messages = messages;
21. logger.traceExit();
22. }
23.
24. public String[] getMessages() {
25. logger.traceEntry();
26. return logger.traceExit(messages, new JsonMessage(messages));
27. }
28.
29. public String retrieveMessage() {
30. logger.entry();
31.
32. String testMsg = getMessage(getKey());
33.
34. return logger.exit(testMsg);
35. }
36.
37. public void exampleException() {
38. logger.entry();
39. try {
40. String msg = messages[messages.length];
41. logger.error("An exception should have been thrown");
42. } catch (Exception ex) {
43. logger.catching(ex);
44. }
45. logger.exit();
46. }
47.
48. public String getMessage(int key) {
49. logger.entry(key);
50.
51. String value = messages[key];
52.
53. return logger.exit(value);
54. }
55.
56. private int getKey() {
57. logger.entry();
58. int key = rand.nextInt(messages.length);
59. return logger.exit(key);
60. }
61. }
Homemade logging
What would those printf() statements look like?
function f(stuff) {
printf(LOG, "%s %s %sn", timestamp, "f{", stuff);
for record in (records) {
process(record);
}
printf(LOG, "%s %s %d recordsn", timestamp, "}", count(records));
}
Maybe you’ll use Log4j.
12
13. @CaryMillsap
Homemade logging
What would those printf() statements look like?
function f(stuff) {
printf(LOG, "%s %s %sn", timestamp, "f{", stuff);
for record in (records) {
process(record);
}
printf(LOG, "%s %s %d recordsn", timestamp, "}", count(records));
}
Maybe you’ll create a --debug option to control it.
13
14. @CaryMillsap
This function: 23.8% debug
function check_for_updates($product, $platform, $version, $debug=0) {
// Find update candidate filenames in distro directory.
$zero_distroversion = "0.0.0.0"; // -INF value for initialization.
$distro_dir = distribution_filename();
if ($dir = opendir($distro_dir)) {
$greatest_distroversion = $zero_distroversion;
if ($debug) echo "<p>Searching files in '$distro_dir':</p>";
if ($debug) echo "<ul>";
while (false !== ($entry = readdir($dir))) { // http://php.net/manual/en/function.readdir.php
if ($entry === "." or $entry === "..") {
continue;
}
if ($debug) echo "<li>";
if ($debug) echo $entry;
if (preg_match("/^$product-([0-9.]+)-$platform./", $entry, $match)) { // Assumption: filename structure.
$distroversion = $match[1];
if ($debug) echo " is a distro match";
if (version_compare($distroversion, $version, ">")) {
if ($debug) echo ", and an update candidate because $distroversion > $version";
if (version_compare($distroversion, $greatest_distroversion, ">")) {
if ($debug) echo ", and the best so far because $distroversion > $greatest_distroversion";
$greatest_distroversion = $distroversion;
$update_filename = $entry;
} else {
if ($debug) echo ", but not the best because $distroversion ≯ $greatest_distroversion";
}
14
15. @CaryMillsap
Why would I do that?
15
Coz my world is the
opposite of this world.
I have to operate the
software I write.
☞
16. @CaryMillsap
We find stepping through a program [with a
debugger] less productive than thinking harder
and adding output statements and self-
checking code at critical places. …More
important, debugging statements stay with the
program; debugging sessions are transient.
—Brian Kernighan and Rob Pike
The Practice of Programming
16
18. @CaryMillsap
What you get with sql_trace
Database calls (dbcalls)
System calls (syscalls)
Values bound to placeholders (“bind variables”)
Query plan (row source) operations
18
22. Edit Email Assign Resolve
Active
Priority
3 – Required
Edit Email Assign Resolve
Opened by Cary Millsap
05/24/2018 (Today) 11:34 AM
Cary Millsap Project: TPS Area: logging Milestone: 1.1.0
Kanban Column
1.1.0.1
@CaryMillsap 22
10001
An operator (e.g., a DBA) must be able to control tracing of selected business
tasks with Oracle’s dbms_monitor PL/SQL package. For example, we should be
able to trace:
- the next OE job
- the next OE BOOK job
- the next job executed by nwells
Operator-controlled tracing of task executions
23. @CaryMillsap
Trace all OE executionsPL/SQL
dbms_monitor.serv_mod_act_trace_enable(
service_name => 'SYS$USERS',
module_name => 'OE',
action_name => dbms_monitor.all_actions,
waits => true,
binds => false,
plan_stat => 'FIRST_EXECUTION'
);
But this works only if your code sets its module name.
23
24. @CaryMillsap
Trace all OE BOOK executionsPL/SQL
dbms_monitor.serv_mod_act_trace_enable(
service_name => 'SYS$USERS',
module_name => 'OE',
action_name => 'BOOK',
waits => true,
binds => false,
plan_stat => 'FIRST_EXECUTION'
);
This works only if your code sets its module and action names.
24
25. @CaryMillsap
Trace all nwells executionsPL/SQL
dbms_monitor.client_id_trace_enable(
client_id => 'nwells',
waits => true,
binds => false,
plan_stat => 'FIRST_EXECUTION'
);
This works only if your code sets its client ID.
25
26. @CaryMillsap
User session handle attributes
Settable and gettable with OCI, JDBC, etc.
Visible in v$session
service_name
module
action
client_identifier
Values can change during a session
Identify sessions or parts of sessions
26
OE/BOOK
OE/PICK
OE/SHIP
Oracle
session
connect
disconnect
set_module('OE', 'BOOK')
set_module(null, null)
set_module(null, null)
set_module(null, null)
set_module('OE', 'PICK')
set_module('OE', 'SHIP')
time
30. @CaryMillsap
The new codepseudocode
sub begin_task(t) {
(mod, act) = split(/ /, t, 2);
setClientInfo(properties(mod, act, getUserName()));
}
sub end_task() {
setClientInfo(properties("", "", ""));
}
30
31. Edit Email Assign Resolve
Active
Priority
3 – Required
Edit Email Assign Resolve
Opened by Cary Millsap
05/24/2018 (Today) 11:34 AM
Cary Millsap Project: TPS Area: logging Milestone: 1.1.0
Kanban Column
1.1.0.1
@CaryMillsap 31
10002
Our connection pooling application makes it difficult to isolate individual user
experiences in the trace data. The Method R Workbench trick of identifying
oceans, islands, and rivers with mrskew --thinktime=z is a start, but we want to
perfectly isolate experiences.
We can do this by printing a unique experience ID (a UUID) to the trace file at the
beginning of a task’s execution, and then printing an empty experience ID at the
end. This will give tools like mrskew a group-by handle that maps perfectly to the
user experience.
Write experience ID to the trace file
41. 41@CaryMillsap
WAIT … nam='SQL*Net message from client' ela= 1202689 …
*** CLIENT ID:(nwells)
*** EXPERIENCE ID:(c6a1c359-5766-4263-9e3e-8e600bb7dba9)
stuff for Experience A
WAIT … nam='SQL*Net message from client' ela= 342
more stuff for Experience A
WAIT … nam='SQL*Net message from client' ela= 1492
yet more stuff for Experience A
…
WAIT … nam='SQL*Net message from client' ela= 4260917 …
*** CLIENT ID:(cshaftig)
*** EXPERIENCE ID:(822a94c6-d27a-4804-84fe-5a7fed03ed9f)
stuff for Experience B
WAIT … nam='SQL*Net message from client' ela= 2928
more stuff for Experience B
…
WAIT … nam='SQL*Net message from client' ela= 5213365 …
*** CLIENT ID:(nwells)
*** EXPERIENCE ID:(733f8c60-2bd3-4fdd-a638-d304f75b1aef)
stuff for Experience C
WAIT … nam='SQL*Net message from client' ela= 855
more stuff for Experience C
…
WAIT … nam='SQL*Net message from client' ela= 2044420 …
42. 42@CaryMillsap
WAIT … nam='SQL*Net message from client' ela= 1202689 …
*** CLIENT ID:(nwells)
*** EXPERIENCE ID:(c6a1c359-5766-4263-9e3e-8e600bb7dba9)
stuff for Experience A
WAIT … nam='SQL*Net message from client' ela= 342
more stuff for Experience A
WAIT … nam='SQL*Net message from client' ela= 1492
yet more stuff for Experience A
…
WAIT … nam='SQL*Net message from client' ela= 4260917 …
*** CLIENT ID:(cshaftig)
*** EXPERIENCE ID:(822a94c6-d27a-4804-84fe-5a7fed03ed9f)
stuff for Experience B
WAIT … nam='SQL*Net message from client' ela= 2928
more stuff for Experience B
…
WAIT … nam='SQL*Net message from client' ela= 5213365 …
*** CLIENT ID:(nwells)
*** EXPERIENCE ID:(733f8c60-2bd3-4fdd-a638-d304f75b1aef)
stuff for Experience C
WAIT … nam='SQL*Net message from client' ela= 855
more stuff for Experience C
…
WAIT … nam='SQL*Net message from client' ela= 2044420 …
44. Edit Email Assign Resolve
Active
Priority
3 – Required
Edit Email Assign Resolve
Opened by Cary Millsap
05/24/2018 (Today) 11:34 AM
Cary Millsap Project: TPS Area: logging Milestone: 1.1.0
Kanban Column
1.1.0.1
@CaryMillsap 44
10003
We’ve had intermittent performance problems with OE BOOK. We don’t want to
trace OE BOOK every time it runs, but it would be nice if we could trace it for
some percentage of executions. We want to control that percentage from a table
that we can modify through a simple APEX application.
Trace only some executions of a given program
46. @CaryMillsap
Trace only some executions
pseudocode
if (should_trace('OE BOOK') {
dbms_session.session_trace_enable(true, false, 'FIRST_EXECUTION');
}
-- Your OE BOOK code
dbms_session.session_trace_disable();
46
47. @CaryMillsap
Trace only some executions
pseudocode
if (should_trace('OE BOOK')) {
dbms_session.session_trace_enable(true, false, 'FIRST_EXECUTION');
}
-- Your OE BOOK code
dbms_session.session_trace_disable();
sub should_trace(t) {
select proportion from trace_control where task = :t;
return (dbms_random.value(0,1) < proportion);
}
47
task_name proportion
OE BOOK 0.05
OE PICK 0.02
… …
trace_control
48. @CaryMillsap
Trace only some executions
pseudocode
sub should_trace(t) {
select proportion from trace_control where task = :t;
return (dbms_random.value(0,1) < proportion);
}
task_name proportion
OE BOOK 0.05
OE PICK 0.02
… …
trace_control
48
p = 0.95 should_trace('OE BOOK') == false
p = 0.05 should_trace('OE BOOK') == true
0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
49. @CaryMillsap
The new code
pseudocode
sub begin_task(t) {
(mod, act) = split(/ /, t, 2);
setClientInfo(properties(mod, act, getUserName());
xid = uuid();
push(xid_stack, (xid, t));
dbms_log.ksdwrt(1, sprintf("EXPERIENCE ID:(%s)", xid));
if (should_trace(t)) {
session_trace_enable(true, true, 'first_execution');
}
}
sub end_task() {
setClientInfo(properties("", "", ""));
pop(xid_stack);
dbms_log.ksdwrt(1, "EXPERIENCE ID:()");
session_trace_disable();
}
49
50. Edit Email Assign Resolve
Active
Priority
3 – Required
Edit Email Assign Resolve
Opened by Cary Millsap
05/24/2018 (Today) 11:34 AM
Cary Millsap Project: TPS Area: logging Milestone: 1.1.0
Kanban Column
1.1.0.1
@CaryMillsap 50
10003
We don't always want to use bind=true and plan_stat='first_execution'. We
want to control those from trace_control as well.
Manage tracing levels from trace_control
52. @CaryMillsap
How we avoid 10046 MIE
1. sql_trace wait=true, bind=false, plan_stat=first_execution
2. If application has lightweight row-by-row executions, we fix it.
3. sql_trace wait=true, bind=true, plan_stat=all_executions
52
54. Edit Email Assign Resolve
Active
Priority
3 – Required
Edit Email Assign Resolve
Opened by Cary Millsap
05/24/2018 (Today) 11:34 AM
Cary Millsap Project: TPS Area: logging Milestone: 1.1.0
Kanban Column
1.1.0.1
@CaryMillsap 54
10004
When a user has a performance problem with the application, she should be able
to click Help › Debug › Trace, which will inspire a properly time-scoped trace of
the next business task she executes.
User controls tracing with Help › Debug › Trace
55. @CaryMillsap
Help › Debug › Trace
How it usually works:
1. User clicks Help › Debug › Trace.
2. This triggers immediate session trace enable.
3. User eventually executes her task.
4. Clicks Help › Debug › Stop Trace.
Not what you want.
55
56. @CaryMillsap
It’s not the trace file you want
You need:
trace enable == task begin
trace disable == task end
Otherwise, you get either too much data,
or not enough.
56
trace disable
task end
task begin
trace enable
trace file
you got
trace file
you want
time
57. @CaryMillsap
Help › Debug › Trace
A user turns on tracing.
vs.
A user expresses the intention to trace the next task execution.
Help › Debug › Trace should set a boolean.
begin_task queries the boolean.
57
58. @CaryMillsap
The new codepseudocode
sub begin_task(t) {
(mod, act) = split(/ /, t, 2);
setClientInfo(properties(mod, act, getUserName());
xid = uuid();
push(xid_stack, (xid, t));
dbms_log.ksdwrt(1, sprintf("EXPERIENCE ID:(%s)", xid));
if (isTraceIntended() or (bind, stat) = should_trace(t)) {
session_trace_enable(true, bind, stat);
}
}
sub end_task() {
setClientInfo(properties("", "", ""));
pop(xid_stack);
dbms_log.ksdwrt(1, "EXPERIENCE ID:()");
session_trace_disable();
}
58
60. @CaryMillsap
More specs (discussion)
• Trace the first OE BOOK execution every hour.
• Trace p% of Larry’s executions, but q% of Nancy’s.
• Trace p% of executions whose durations have one of the top ten variance-to-
mean ratios (VMR) in your application.
• Trace only if the job is less than p% complete after running for m minutes.
Could you do these even if you don’t have source code access? How?
60
61. @CaryMillsap
Hundreds of specs you could meet
Trace when you need.
Persist every response time.
Predict response time problems.
Track pathway through the application.
Write harvesters, uploaders, profilers for the data.
Log to shared memory segments for ultra-high throughput.
You can build anything you want; application self-measurement is no big deal.
61
62. @CaryMillsap
For more information…
62
The definitive guide to accurate, high-precision
measurement of user performance experiences,
for Oracle application developers and database
administrators.
Cary V. Millsap
TM
MeTHOD R
TM
The Guide to
MASTERING
ORACLE
TRACE DATA
Second Edition
REVISED
UPDA
TED
NEW PA
G
ES
1 3 2
Available at