“Load profile” section of the AWR report contains some extremely useful information, and yet it is very often overlooked (often in favor of instance efficiency percentages, which is easier to read but much more likely to mislead). I decided to make some sort of a short guide for it, describing how different statistics in it can be used to better understand performance of a database.
Everything that you do in a database is protected by redo. Redo is a collection of so-called “change vectors” that tell Oracle how to repeat an operation on data if necessary. Even though SELECTs can also generate some redo, the main sources of redo are (in roughly descending order): INSERT, UPDATE and DELETE. For INSERTs and UPDATE s, the size of redo is close to the amount of data created or modified. For DELETEs, you only need to know the rowid’s of deleted rows to repeat the operation, so if the rows are “fat”, then the size of redo may be much smaller than the size of deleted data.
High redo figures mean that either lots of new data is being saved into the database, or existing data is undergoing lots of changes.
How high is high? Databases are not created equal, so there is no universal standard. However, I find it useful multiplying redo per second by 86,400 (number of seconds there are in a day) and compare it to the size of the database — if the numbers are within the same order of magnitude, then this would make me curious. Is the database doubling in size every few days? Or is it modifying almost every row on a daily basis? Or maybe there is something going on that I don’t know about?
What do you do if you find that redo generation is too high (and there is no business reason for that)? Not much really — since there is no “SQL ordered by redo” in the AWR report. Just keep an eye open for any suspicious DML activity. Any unusual statements? Or usual statements processed more usual than often? Or produce more rows per execution than usual? Also, be sure to take a good look in the segments statistics section (segments by physical writes, segments by DB block changes etc.) to see if there are any clues there.
Logical reads, block changes, physical reads/writes
Logical reads is simply the number of blocks read by the database, including physical (i.e. disk) reads, and block changes is fairly self-descriptive. These statistics tell the nature of the database activity (read-mostly, write-mostly, a little bit of both) and its scale at the time of the report. It also gives you an idea how well data caching works in the database (but you can also see that directly from the buffer cache hit ratio in the “instance efficiencies” section).
If you find those number higher than expected (based on usual numbers for this database, current application workload etc.), then you can drill down to the “SQL by logical reads” and “SQL by physical reads” to see if you can identify specific SQL responsible.
A user call is when a database client asks the server to do something, like logon, parse, execute, fetch etc. This is an extremely useful piece of information, because it sets the scale for other statistics (such as commits, hard parses etc.).
In particular, when the database is executing many times per a user call, this could be an indication of excessive context switching (e.g. a PL/SQL function in a SQL statement called too often because of a bad plan). In such cases looking into “SQL ordered by executions” will be the logical next step.
Parses and hard parses
A parse is analyzing query’s text and optionally, optimizing a plan. If plan optimization is involved, it’s a hard parse, otherwise a soft parse.
As we all know, parsing is expensive (performance-wise). Excessive parsing can cause very nasty performance problems (one moment your database seems fine, the next moment it comes to a complete standstill). Another bad thing about excessive parsing is that it makes troubleshooting of poorly performing SQL much more difficult.
How much hard parsing is acceptable? It depends on too many things, like number of CPUs, number of executions, how sensitive are plans to SQL parameters etc. But as a rule of a thumb, anything below 1 hard parse per second is probably okay, and everything above 100 per second suggests a problem (if the database has a large number of CPUs, say, above 100, those numbers should be scaled up accordingly). It also helps to look at the number of hard parses as % of executions (especially if you’re in the grey zone).
If you suspect that excessive parsing is hurting your database’s performance:
1) check “time model statistics” section (hard parse elapsed time, parse time elapsed etc.)
2) see if there are any signs of library cache contention in the top-5 events
3) see if CPU is an issue.
If that confirms your suspicions, then find the source of excessive parsing (for soft parsing, use “SQL by parse calls”; for hard parsing, use force_matching_signature) and see if you can fix it.
Sort operations consume resources. Also, expensive sorts may cause your SQL fail because of running out of TEMP space. So obviously, the less you sort, the better (and when you do, you should sort in memory). However, I personally rarely find sort statistics particularly useful: normally, if expensive sorts are hurting your SQL’s performance, you’ll notice it elsewhere first.
Establishing a new database connection is also expensive (and even more expensive in case of audit or triggers). “Logon storms” are known to create very serious performance problems. If you suspect that high number of logons is degrading your performance, check “connection management elapsed time” in “Time model statistics”.
Executes statistic is very important for analyzing performace, but what I had to say about it I’ve already said above in “user calls” and “parses and hard parses” sections.
This is another extremely important statistic, both on the general (i.e. creating context for understanding the rest of the report) and specific (troubleshooting performance problems related to transaction control) levels. The AWR report provides information about transactions and rollbacks, i.e. the number of commits can be calculated as the difference between the two. Rollbacks are expensive operations, and can cause performance problems if used improperly (i.e. in tests, to revert the database to the original state after testing), which can be controlled either by reducing the number of rollbacks or by tuning rollback segments. Rollbacks can also indicate that a branch of code is failing and thus forced to rollback the results (this can be overseen if resulting errors are not processed or rethrown properly).
Excessive commits can lead to performance problems via log file sync waits .
How many is excessive? Once again, this entirely depends on the database. Obviously, OLTP databases commit more than DWH ones, and between OLTP databases the numbers can vary several orders of magnitude. For the databases that I worked with, below 10-20 commits per second there never was a problem, and above 100-200 there almost always was (when not sure, look in “top timed events”: if there are no “log file sync” waits up there, then you’re probably okay!).