WL#4816: PERFORMANCE_SCHEMA Summaries

Affects: Server-6.x — Status: Un-Assigned — Priority: Low

The initial description here has been shifted from the "Summaries"
section of WL#2360 Performance Schema. This task depends on WL#2360.

"Summaries" is not a requirement. Maybe we'll have zero summary tables
in 6.1. Therefore this section does not require approval. However, it
must be here to show that, with WL#2360 as a basis, we can produce what
we'll want. After we finish WL#2360, Peter will shift this description
to a new task.

[ ADVANCE PSEUDO GROUP BY ]

Suppose the EVENTS_WAITS_HISTORY table contained rows, not just for the
last 10 events, but for all events since the instance started.
Then we could say:
SELECT EVENT_NAME, COUNT(*) AS COUNT_STAR, SUM(TIMER_WAIT) AS SUM_TIMER_WAIT
FROM EVENTS_WAITS_HISTORY
WHERE /* filter_condition, e.g. "in a previous statement" */
GROUP BY EVENT_NAME.GENUS
And we'd have a lovely table like this:
EVENT_NAME                    COUNT_STAR               SUM_TIMER_WAIT
--------                      ----------               --------------
Wait/Synch/MUTEX/LOCK_open            14                          140
Wait/Synch/MUTEX/LOCK_ha_data          8                           80
Wait/Synch/MUTEX/LOCK_logger          22                          220

Terminology notes: here EVENT_NAME is the "grouping column", COUNT and
SUM are "aggregates", TIMER_WAIT is an "aggregating column", the
result set is a "summary table". You'll see those terms several times.

All summary information is based on groupings and aggregatings.
The only flaw is that it's "pseudo". There is no table that goes
back forever. Shortly after producing an EVENTS_WAITS_HISTORY row, we risk
overwriting it (see section "Ring Buffers"). So, to provide summary
information, we'll have to do the grouping at the same time as, or
shortly after, the production of the EVENTS_WAITS_CURRENT row.

To some extent, that means we must guess what the user will want.
But we can guess well. We can provide a lot of tables for the user
to pick from (by enabling in SETUP_CONSUMERS). We can make sure that
the tables include anything that's been requested before or provided
before for MySQL or for some other DBMS.

[ WHAT WE CAN USE FOR AGGREGATING ]

These are the possible aggregations, in order of increasing difficulty.
COUNT(*)           Easy. If there's a row, then ++COUNT_STAR somewhere.
SUM(TIMER_WAIT)    Easy. Subtract START_TIME from END_TIME (or from
                   current time if END_TIME is still null), and add
                   that to SUM_TIMER_WAIT somewhere.
AVG(TIMER_WAIT)    Easy. The consumer routine must calculate averages.
MIN(TIMER_WAIT)    A bit harder. The typical algorithm for calculating
or                 minimum|maximum in a list will have a line like this:
MAX(TIMER_WAIT)    "if (curr_value < min_value) then min_value = curr_value;"
                   but that might cause a 'jump' instruction at assembly
                   level. If we find that C optimizers use conditional-move
                   instructions rather than jumps, we'll be happier.
STDDEV(TIMER_WAIT) Impossible. We won't do equivalents for any of the other
                   MySQL aggregating functions like BIT_XOR, GROUP_CONCAT,
                   STDDEV, and the others listed in the reference manual
                   http://dev.mysql.com/doc/refman/6.0/en/group-by-functions.html
                   because even if we could do them, who would care?

TIMER_WAIT is the basis for most aggregations. There were other possibilities:
MIN|MAX(START_TIME|END_TIME) if the timer is wall-clock this makes some sense
SUM(SPINS) remembering that there might be other 'extra' columns like SPINS.
We ignore these other possibilities.

[ WHAT WE CAN USE FOR GROUPING ]

These are the possible grouping columns:
THREAD_ID           Actually grouping "by thread" is not a problem because
                    it's implicit. All summarizations are done within a thread.
                    We do not update counters of other threads, and we do not
                    update global counters, except in a special case (see later
                    discussion of "global summaries"). This is one of the
                    reasons we won't need mutexes.
EVENT_NAME          The components of EVENT_NAME are all candidates for
                    grouping. To answer questions like "how many mutex_locks
                    occurred" or "what is the average time for each type of
                    mutex", we'll need a summary table that has a row for
                    each genus. And genera will be accumulated into orders,
                    which are accumulated into classes, all the way up the
                    taxonomy line.

Notice that EVENT_NAME, our favourite grouping column, has a fixed number of
possible values and they are all knowable in advance. (Actually a few can be
added by storage engines during server initialization but that's still "in
advance" for most practical purposes.) This is an important consideration.
It means that we can preallocate memory for the grouping permanently, and
it means that we can point to the memory quickly, because it's fixed offset.

We might get a request for a "per minute" grouping, based on
ROUND(TIMER_START/60000000000) or something similar. We won't
do it because we can't precalculate the possible values. But
it's irrelevant anyway, because groupings by time periods can
be done with "Samplings". (See later section "Samplings".)
So we won't use any timer columns as grouping columns.

We might get a request for a grouping based on OBJECT_INSTANCE_BEGIN.
This would be great for answering really detailed questions like
"how many times did somebody access row#5" or "what was the time
elapsed when we wrote to a file starting at byte#16384". Sorry,
there are just too many possible values, Nobody saw a way to do it.
Histograms for OBJECT_INSTANCE_BEGIN might be a substitute, but we
won't have them either.

I'll talk later about "per statement" and "per object" groupings.

I think it's unlikely that people would want a grouping by EVENT_ID
or SPINS. And when something's unlikely, it's out of the question.

Combining the considerations about aggregating and grouping, we know
therefore there is an 'aggregators' struc which will contain these fields:
  NAME             LENGTH  DESCRIPTION
  grouping_type         2  Identifies genus or other category from event_name
  count_star            8  We ++count_star whenever we end a wait
  sum_time_elapsed      8  We add to sum_time_elapsed when we end a wait
  min_time_elapsed      8  We calculate min_time_elapsed when we end a wait
  max_time_elapsed      8  We calculate max_time_elapsed when we end a wait
Total length = 42 bytes for one aggregators-struc occurrence.

[ DEFINITION OF A TYPICAL TABLE ]

Table name = EVENTS_WAITS_SUMMARY_BY_THREAD_BY_GENUS
List of columns and data types:
  THREAD_ID             BIGINT
  COUNT_STAR            BIGINT
  EVENT_NAME            VARCHAR(128)
  SUM_TIMER_WAIT        BIGINT
  MIN_TIMER_WAIT        BIGINT
  MAX_TIMER_WAIT        BIGINT
  AVG_TIMER_WAIT        BIGINT

Compare the definition of EVENTS_WAITS_CURRENT:
columns EVENT_ID SPINS OBJECT_SCHEMA OBJECT_NAME OBJECT_TYPE
OBJECT_INSTANCE_BEGIN are gone,
column TIMER_WAIT is summarized,
column COUNT_STAR is added.

[ NESTING-EVENT SUMMARIES ]

A "statement" might cause multiple "waits" or "file" events.
So we say that "wait" or "file" events can be "nested" inside "statements".
There are several levels of nesting in classes of events, for example
Transaction -> Statement -> Stage (e.g. "sort") -> Wait. So far there's no
firm definition of the classes and nestings, so let's just posit
that they exist, and that "statement" can be a nesting event for a "wait".

It's common to require grouping by a nesting event.
For example kostja_notes.txt (attached to WL#2360) asks for
"Example requirements:
 - wait time accumulated per SQL statement
 - physical reads per SQL statement"
And the support wishlist
[mysql intranet]/secure/wiki/ServerMonitoringWishlist
asks for "reads per statement".

However, we shouldn't use "statement id" as a grouping column for reasons
mentioned in the "what we can use for grouping" subsection, above.
So this case requires special handling. Our rule will be:
You must add to the aggregators for a nesting event, as well as your own.
Luckily the nesting event is easy to find because each thread, at any given
moment, has only one running top-level statement, one running stage, one
running wait, etc.
No table lookup is necessary.

The performance-struc for a statement event will have additional fields for
these aggregators, as well as its own:
  NAME             LENGTH  DESCRIPTION
  thread_id             ?  See earlier section.
  event_id              8  See earlier section.
  event_name            8  See earlier section.
  timer_start           8  See earlier section.
  timer_end             8  See earlier section.
  spins                 4  See earlier section.
  object_id             8  See earlier section.
  object_instance_begin 8  See earlier section.
  nested_1_level_below  80*42  occurrences of 'aggregators' struc for stages
  nested_2_levels_below 80*42  occurrences of 'aggregators' struc for waits

The additional "nested_*" fields will be reflected in the
EVENTS_STATEMENTS_CURRENT and EVENTS_STATEMENTS_HISTORY tables.

To save space and time, the additional "nested_*" fields
will have only a small number of occurrences. There will
be an occurrence for each "family", not for each "genus".
(That's why I say LENGTH is 80*42: guessing 80 families and 42
bytes per aggregator struc.) In the name "wait/synch/mutex/lock_open"
the family is "mutex" and the genus is "lock_open".
So what the user will see is
SELECT * FROM EVENTS_STATEMENTS_CURRENT\G
... /* all the columns described for EVENTS_WAITS_CURRENT, above */
WAIT_SYNCH_MUTEX_COUNT_STAR
WAIT_SYNCH_MUTEX_SUM_TIMER_WAIT
WAIT_SYNCH_MUTEX_MIN_TIMER_WAIT
WAIT_SYNCH_MUTEX_AVG_TIMER_WAIT
WAIT_IO_FILE_READ_COUNT_STAR
etc.

So, at the cost of a lot of memory, we have something that shows
detail statistics for every stage of a statement (which means that
SHOW PROFILE is redundant), and for every class of wait of a
statement, for the last 10 statements. In addition, of course,
we will have the statement's own aggregations which are updated
when the statement ends. (I've said elsewhere that the EVENTS_STATEMENTS_
tables look pretty much the same as the EVENTS_WAITS_ tables, so there
is a table EVENTS_STATEMENTS_HISTORY with 10 rows in it.)

(By the way, there might be a big difference between statement's
total time and accumulated time of nested events. That's because the
"time" for any event includes time swapped out. For a wait, that's
what you want anyway. And anyway the real work might be done by a
backgrounder. And not every bit of code within a statement is
instrumented.

Nesting-event summaries are independently stored, so they may be enabled
even if the lower-level summaries are disabled.

[ HISTOGRAMS ]

The proposal is "no histograms", but let us consider them.

A histogram, like COUNT/SUM/AVG/MIN/MAX, is a type of aggregation.
So as well as COUNT(*), we could have HISTOGRAM_COUNT(TIMER_WAIT).
It answers the question "how many times did an instrument take
less than x seconds, how many times did it take less than y seconds,
how many times did it take less than z seconds, and so on".
So it returns multiple integers showing counts for ranges of times.
Possible alternate word: "quantize".

As far as I know, nobody has asked MySQL for summaries with histograms.
But histograms are known to be an excellent way to present information,
so there are precedents outside the DBMS industry.

We will use exponential powers-of-2 buckets. Reasons:
(a) bit scanning can be quick on some processors, for example
    on x86-64 you can find out "what is the index of the most
    significant bit" with a single instruction, BSR
(b) we won't have to figure out in advance what the ranges are
Posit 8 buckets for < 256, < 1024, < 4096, < 16384, < 65536, < 262144, <
1048576, >= 1048576.
Some users will want fixed-width buckets (0 - 999, 1000 - 1999, 2000 - 2999, etc.)
but that is more trouble (although it would require a less exotic
instruction than BSR, since this is a case for integer division).

There is a table EVENTS_WAITS_SUMMARY_WITH_HISTOGRAMS.
It has the same columns as EVENTS_WAITS_SUMMARY, and 8 additional columns:
HISTOGRAM_COUNT_TIME_ELAPSED_LESS_THAN_256 BIGINT,
HISTOGRAM_COUNT_TIME_ELAPSED_LESS_THAN_1024 BIGINT,
HISTOGRAM_COUNT_TIME_ELAPSED_LESS_THAN_4096 BIGINT,
HISTOGRAM_COUNT_TIME_ELAPSED_LESS_THAN_16384 BIGINT,
HISTOGRAM_COUNT_TIME_ELAPSED_LESS_THAN_65536 BIGINT,
HISTOGRAM_COUNT_TIME_ELAPSED_LESS_THAN_262144 BIGINT,
HISTOGRAM_COUNT_TIME_ELAPSED_LESS_THAN_1048576 BIGINT,
HISTOGRAM_COUNT_TIME_ELAPSED_GREATER_THAN_OR_EQUAL_TO_1048576 BIGINT

For example, suppose that we have read a row 5 times.
Twice the operation took 8000 canonical time units (pseudo-picoseconds),
three times it took 50000 canonical time units. The statement
SELECT * FROM EVENTS_WAITS_SUMMARY_WITH_HISTOGRAMS
WHERE EVENT_NAME LIKE 'FILE/IO/READ%'\G
will return
EVENT_NAME FILE/IO/READ
...
COUNT_STAR                                         5
SUM_TIME_ELAPSED                              166000
...
HISTOGRAM_COUNT_TIME_ELAPSED_LESS_THAN_16384       2
HiSTOGRAM_COUNT_TIME_ELAPSED_LESS_THAN_65536       3
...

This looks useful. So why is the proposal to reject histograms?
Well, partly because it's a bunch of work to make it fast
(I doubt that optimizers will use the right instructions).
More importantly because it's a bunch of memory,
even if we use only 8 buckets that's 64 bytes per summary row,
and assume 500 summary rows per thread. It's true that we
don't have to use that space if we disable the histograms
tables in SETUP_CONSUMERS, but almost all users would disable,
so almost no users would benefit from histogram support.

[ OBJECT SUMMARIES ]

A grouping "by object" is what people are asking for when they say
"* Track blocks read per file * Track blocks written per file
* Track I/O per second average per file"
[mysql inside intranet address]/wiki/ServerMonitoringWishlist
And one of the Google patches can give counts of reads and
writes per table, or per index.
I've also heard a request for "how often has a procedure been called".

Generally we want to summarize for "database objects" (base tables,
indexes, stored procedures, functions, events, triggers, modules,
constraints) or named "session objects" (prepared statements,
cursors, conditions, variables, savepoints). We don't worry about
summarizing for things like mutexes because they'd be both easy and
unnecessary. We can get summaries for all the lock_open mutexes without
needing to know the address that was used for lock_open.

At first glance it looks simple: just declare that OBJECT_NAME etc.
are grouping columns, or do the same things that we did for
"nesting-event summaries". But both those methods fail because:
* the number of objects isn't fixed and might be large
* the location of the object struc isn't known, it must be looked up
* the object name columns are strings, so they take time to compare.

So we need WL#2760."Super-Database (real Data Dictionary)".
I'm assuming that WL#2760 will give us persistent in-memory descriptors
for all schema objects, so we'll be able to use an address or offset
whenever we're using the object. When we have that, object summaries will
be easy. However, WL#2760 will not be available until MySQL 6.2.

In the meantime, we could offer a restricted-functionality solution.

This works only for base tables in the table cache.
The person doing the instrumenting has to pass  the address
of the table descriptor. We don't actually store the summary
information in the table descriptor, but we need it as a
reference point for the persistent information.

First: we have a new SETUP table. Call it SETUP_OBJECTS.
It contains: OBJECT_TYPE VARCHAR(64), SCHEMA NAME VARCHAR(64),
OBJECT_NAME VARCHAR(64), ENABLED ENUM('Y','N'), AGGREGATED ('Y','N').
Initially this table is empty. A user can say
INSERT INTO SETUP_OBJECTS('TABLE','TEST','T','Y','Y');
('TABLE' meaning base table is the only possible type but
the TYPE column is just here for future use.)
This means, essentially, that we want to enable object
summarizing for table test.t.

Second: in the per-thread memory, we have an area for
object summaries. For one object, it contains:
schema name
object name i.e. table name
pointer to table cache
multiple occurrences of 'aggregator' struc
The number of occurrences is fixed for an instance, it
depends on a mysqld server-startup-option. Thus there
is a limit to the number of tables that one can insert
into SETUP_OBJECTS. Also the number of occurrences will
depend on the number of 'families', but in the case of
a table there are only four families: read_row, update_row,
delete_row, write_row. So we're looking at approximately
128 + 128 + 8 + 42 * 500 * 4 = 85000 bytes per thread,
if we allow for aggregating of 500 tables.

Third: we change the instrumentation requirement so that,
for base tables, the person writing the instrument must
specify the "object name" in a way so that we can interpret it
as a reference to the table cache, rather than a string.
This may be stored in 'performance-struc' as well.

Fourth: the instrument end-timer ("end_wait") for tables will
differ from the instrument end-timer for other objects. It will
check: is the table identifier equal to one of the
'pointer to table cache' items for the thread?
(This is a simple integer comparison but it might be
repeated 500 times, so there is variable extra overhead
for table summarizing.) If so, and the enabled and
aggregating flags are on, then MySQL adds to the
aggregator fields, in the same manner as when it adds
to nesting-event aggregator fields.

Fifth: there are summary tables, OBJECTS_SUMMMARY_BY_THREAD_BY_TYPE
and OBJECTS_SUMMARY_GLOBAL_BY_TYPE. They'll contain the usual
sort of summary columns (COUNT_STAR, SUM_TIMER_WAIT, etc.).
By searching the global table, assuming the instrument points
are around read/write/update/delete for rows, you'll have the
counting and timing for all DML done on the table.
There is no 'history' table for objects, and the counts just
keep going up because this description doesn't allow for resetting
the counts.

The implementor will doubtless have some trouble with robustness,
given that users might be updating SETUP_OBJECTS, and the contents
of the table cache might be changing, while aggregating occurs.
Once again, we will just say: very occasionally there will be
erroneous information, we just document that's the way things are.

Once WL#2760 is done and we add support for other object types
besides 'TABLE', very little will change from the user's point
of view. The table and column descriptions will be the same.

[ INFINITE HISTORIES ]

The proposal is "no infinite histories", but let's consider them.

At the outset, I said that we have to update summaries during the
instrumentation because "There is no table that goes
back forever." But what if there was? There are two possibilities:
* Add 3GB of memory to your machine. Now there is enough space for
  an EVENTS_WAITS_HISTORY_LONG_LONG_LONG table.
* Enable file trace. Now there is a disk file instead of memory.
  We can convert it to a MySQL table.

With such scenarios, the instrumentation doesn't need to do any
summarizing at all. We can assume that users will do their own
ad-hoc grouping and aggregating for everything.

But, if we require lots of memory, we make the instrumentation
obtrusive. Our objective is to make all users comfortable with
monitoring always on.

And trace files have high overhead, as mentioned elsewhere (WL#4878).

So assume there are no infinite histories.

[ HIGHER-LEVEL SUMMARIES ]

Earlier we said that there are multiple summary tables, each for a
different EVENTS_NAME level, for example EVENTS_WAITS_SUMMARY_BY_FAMILY and
EVENTS_WAITS_SUMMARY_BY_GENUS. but there is only one underlying structure,
the summaries for "by genus". For all tables above the genus level
(family, order, class, etc.), the instrumentation does nothing at all.
We know that the Consumer can calculate the per-family summaries by
adding up the per-genus summaries.

Higher-level summaries are calculated, so they're disabled if the
lower-level summaries are disabled.

[ GLOBAL SUMMARIES ]

A global summary would be processed thus:
There are also occurrences of performance-structure-summary in global memory.
But these global summaries are not totals for all current jobs.
They are only for non-current jobs, that is, jobs that have terminated.
Why don't we update the global summaries at the same time as the per-thread
summaries? Because we fear conflicts, with two threads updating the global
summaries at the same time. That might be harmless if the only operation
is ADD. But the second reason is that we want the Provider's End procedure
("end_wait") to be as fast as possible, and so we'll pass extra work to the
Consumer. When the Provider thread is about to terminate, it gets a mutex
(call it Terminator mutex) and then adds all per-thread summaries to the
global summaries.
When a Consumer thread is about to display global information, for example
"the total number of mutex acquisitions for all sessions since the server
started", it must go through all the per-thread summaries and add them in
its temporary storage, and then add the global summaries.

So the important things to understand are that all summmaries are done
"within a thread", thus removing contention problems, which is important
because Providers never use mutexes. But if a thread is killed and its
memory is deallocated, then all its tables re copied to a single
"global summaries" area. This copying has to be under mutex control,
and Consumers must see the mutex, but it's not an exception to our
"Providers never use mutexes" rules. I mean the instrumentation has no mutexes.

This does mean that monitoring a dead thread is impossible.
But we have merely decided that information about dead threads is less
important, so it ends up in summaries, samples, and user-generated
histograms. Its details disappear.

The consumer of a "global" summary table will have to go through all the
threads and add them up, and then add the summaries from the dead-threads
global area.

Global summaries are calculated, so they're disabled if the
by-thread summaries are disabled.

[ THE ROUTINE ]

Simply put, a per-thread summary would be processed thus:
In the End procedure ("end_wait"), the Provider takes values from
performance-structure and adds them to a performance-structure-aggregator.
The summary is "by class of event", still within the thread. For example,
when we finish a mutex call, we calculate the total canonical time units waited
(.timer_end - .timer_start) and add it to
performance-structure-aggregators [mutex] . sum_timer_wait. And we
increment performance-structure-summary [mutex] . count_star.
We will need this summary for another table, too.

Remember that intrumentation has a 'start' (before the instrumented code)
and an 'end' (after the instrumented code). All summarizing is in the 'end'
("end_wait"). The pseudocode for a WAIT instrumentation is:

/* Do the non-summary instrumentation code. */
if (summary table for statement is enabled)
  ++statement.summary.count_star;
  statement.summary.sum_elapsed+=elapsed-time-for-this-instrument;
  conditional-move(statement.summary.min_elapsed,elapsed-time-for-this-instrument);
  conditional-move(statement.summary.max_elapsed,elapsed-time-for-this-instrument);
if (summary table for this wait genus is enabled)
  ++wait.summary[genus].count_star;
  wait.summary[genus].sum_elapsed+=elapsed-time-for-this-instrument;
 
conditional-move(wait.summary[genus].min_elapsed,elapsed-time-for-this-instrument);
 
conditional-move(wait.summary[genus].max_elapsed,elapsed-time-for-this-instrument);

In assembler, with wonderful optimization, with all summaries enabled,
this will take 2 not-taken conditional-jump instructions, 4 increment
or add instructions, 1 multiplication to get canonical time units from
the units that the timer returns, 4 conditional moves, and 1/5 cache miss. 55
cycles.
Eventually there will be 2 other nesting-event classes besides 'statements', so
multiply by 2, and say 110 cycles.

This is a good time to estimate the total cost.
It's 110 cycles overhead in speed terms, and in memory terms it's
42 bytes per 'aggregators' struc
times 500 occurrences of 'aggregators' in genus-level summaries
plus 2 occurrences of 'aggregators' in statement or stage summaries
times 200 threads
plus 500 occurrences of 'aggregators' in global summaries
Typically, then, it will all add up to somewhere around 1MB.

Our cost estimate, then, is 110 extra cycles per instrument and 1MB extra memory.

[ TRICKS ]

I think that the cost is acceptable on all possible platforms.
But let's think about a few ways to reduce.
These are tricks; they are recommendations; they are not requirements.

1. Be cheap with SETUP_CONSUMERS.
Effectively SETUP_CONSUMERS acts as a filter on production of summary
tables. Disabling saves a tiny amount of time, but more importantly,
it can save memory. Suppose that there are 1000 summary tables, but
we have a fixed limit, we say that users cannot enable more than 100.
Now, allocate memory for only 100 strucs, and one list of pointers
from the enabled-summaries list to the strucs themselves.

2. Summarize 1 time for last 10 performance-strucs, instead of 10 times
for laat 1 performance-strucs.
The current proposal is that the summary happens for every instrumentation,
during end_timer. But if we summarized every tenth time, and went through
all 10 rows in events_waits_history, then we wouldn't lose any information.
This won't reduce the number of calculations for the summaries themselves.
But it will reduce the number of checks of enabled flags, and it makes
cache hits more probable.

3. Use 32-bit not 64-bit fields. Usually COUNT_STAR and SPINS won't
overflow for several days. So we could use less memory
if we didn't have 64-bit fields for every summary item.

4. Group by family not by genus. This is just because we might have too
many genera (I'm estimating 500 genera). So another way to accomplish
the same purpose is to disable instrumenting for many genera, permanently.

[ EXAMPLES ]

Assuming default schema = performance schema.

"What is the total number of wait calls of any type since instance start?"
SELECT COUNT_STAR FROM EVENTS_WAITS_SUMMARY_GLOBAL;

"For the current statement on thread 17, show the statement elapsed time,
the total time spent in the last 10 mutexes, and the average time spent on
all mutexes of type 'lock_open'".
SELECT TIMER_WAIT FROM EVENTS_STATEMENTS_CURRENT WHERE THREAD_ID = 17
UNION ALL
SELECT SUM(TIMER_WAIT) FROM EVENTS_WAITS_HISTORY WHERE THREAD_ID = 17
UNION ALL
SELECT WAIT_SYNCH_MUTEX_AVG_TIMER_WAIT FROM EVENTS_STATEMENTS_CURRENT
WHERE WAIT_SYNCH_MUTEX_EVENT_NAME = 'Wait/Synch/Mutex/Lock_open';

"Show contents of all waits summary tables."
SELECT * FROM EVENTS_WAITS_SUMMARY_BY_THREAD_BY_CLASS;
SELECT * FROM EVENTS_WAITS_SUMMARY_BY_THREAD_BY_ORDER;
SELECT * FROM EVENTS_WAITS_SUMMARY_BY_THREAD_BY_FAMILY;
SELECT * FROM EVENTS_WAITS_SUMMARY_BY_THREAD_BY_GENUS;
...
SELECT * FROM EVENTS_LOCKS_SUMMARY_BY_THREAD_BY_CLASS;
...
SELECT * FROM EVENTS_STAGES_SUMMARY_BY_THREAD_BY_CLASS;
...
SELECT * FROM EVENTS_STATEMENTS_SUMMARY_BY_THREAD_BY_CLASS;
...
SELECT * FROM EVENTS_WAITS_SUMMARY_GLOBAL_BY_CLASS;
SELECT * FROM EVENTS_WAITS_SUMMARY_GLOBAL_BY_ORDER;
SELECT * FROM EVENTS_WAITS_SUMMARY_GLOBAL_BY_FAMILY;
SELECT * FROM EVENTS_WAITS_SUMMARY_GLOBAL_BY_GENUS;
...
SELECT * FROM EVENTS_LOCKS_SUMMARY_GLOBAL_BY_CLASS;
...
SELECT * FROM EVENTS_STAGES_SUMMARY_GLOBAL_BY_CLASS;
...
SELECT * FROM EVENTS_STATEMENTS_SUMMARY_GLOBAL_BY_CLASS;
/* several hundred tables in all, depending how many classes we make */

You must be logged in to tag this worklog

No Comments yet

Votes

Not yet rated.
You must be logged in to vote.

Watches

0 members are watching this worklog
You must be logged in to track this worklog.

Provide Feedback

Please note:
HTML will be purified, but we allow for a number of HTML tags so that you have the flexibility to decorate your comment text to some extent. The comments allow the following HTML tags:

strong, b, em, blockquote, a, code, pre

To put code into your comment, simply encapsulate your code with
[code language="XXX"][/code], where XXX is any common language, for instance "PHP", "SQL", "C", etc.



You must be logged in to comment