 |
Oracle Database 11g:
The Top New Features for DBAs and Developers
by Arup Nanda  |
And Don't Forget...
Finally, I want to provide an introduction to many miscellaneous features that you will come to know and love in Oracle Database 11g.
New Processes
Each new version of Oracle Database brings forth a new set of abbreviations for new processes. Here is the list for Oracle Database 11g Release 1:
Process |
Name |
Description |
ACMS |
Atomic Controlfile to Memory Server |
Only applicable in a RAC instance. When a distributed SGA update is issued, ACMS ensures that the update happens on all instances. If the update fails on one, this process also rolls it back on all instances. Think of ACMS as a two-phase commit coordinator process for SGA updates in a RAC cluster. |
DBRM |
Database Resource Manager |
Implements the resource plans and other resource manager-related tasks |
DIA0 |
Diagnosibility process 0 |
Detects hang situations and deadlocks. In the future there may be more than one process, so the name is set as diag0. The other processes, if they come in the future will be named dia1, dia2, etc. |
DIAG |
Diagnosibility process |
Performs the diagnostics, dumps trace files, if necessary and performs global oradebug commands |
FBDA |
Flashback Data Archiver |
Oracle Database 11g has a new “Flashback Archives” to write the changes made to a table (refer to “Transactions Management” installment of this series). This process writes the flashback archives. |
GTX0 |
Global Transaction Process 0 |
In a RAC cluster, Oracle Database now provides improved handling of XA transactions. This process coordinates XA transactions. If the database load on XA grows, more processes are automatically created with names GTX1, GTX2, upto GTXJ. |
KATE |
Konductor (Conductor) of ASM Temporary Errands |
Undoubtedly the grandest name of all new processes. This is seen on ASM instances; not the database. (Refer to the installment on this series on ASM for the new feature Fast Disk Resync.) When a disk goes offline, this process performs a proxy I/O on its behalf to an ASM metafile. |
MARK |
Mark AU for Resync Koordinator (coordinator) |
Refer to the ASM installment
for more details on the resiliency of the ASM diskgroups. When a disk fails, it becomes offline, causing writes to miss. In that case, this process marks the ASM allocation units (AUs) as stale. When the disk comes online, the stale segments will be refreshed. |
SMCO |
Space Manager |
SMCO is the master space management process that dynamically allocates and deallocates space. It spawns slave processes Wnnn to implement the tasks. |
VKTM |
Virtual Keeper of TiMe process |
Provides a wall clock equivalent (with 1 second updates). When running at elevated priority, it provides a 20 ms update. |
W000 |
Space Management Worker Processes |
Implements the instructions received from SMCO. More processes are spawned as needed with names like W000, W001 and so on. |
Colored SQL
This new feature doesn't paint the SQL statement in color; rather, it sort of marks it as "important."
Suppose you are troubleshooting a performance issue and you suspect a specific SQL statement contributing to the problem. You want the SQL statement to be captured in every Automatic Workload Repository (AWR) snapshot. But AWR snapshots do not capture all SQL statements; just the top ones. How can you force a specific SQL to be captured, regardless of its inclusion in the top SQLs?
The procedure add_colored_sql() in the package dbms_workload_repository marks the SQL as "colored", or important enough to be captured in every AWR snapshot regardless of whether the SQL is in top SQLs. First, identify the SQL statement and then get its SQL_ID. To color it, use:
begin
dbms_workload_repository.add_colored_sql(
sql_id => 'ff15115dvgukr'
);
end;
To find out which SQLs have been colored, you can query the AWR table WRM$_COLORED_SQL:
SQL> SELECT * FROM wrm$_colored_sql;
DBID SQL_ID OWNER CREATE_TI
---------- ------------- ---------- ---------
2965581158 ff15115dvgukr 1 05-APR-08
Thereafter the SQL statement with ID ff15115dvgukr will be captured in every snapshot, even if it's not in the top SQL statements. (Of course, the SQL must be present in the library cache to be captured in the AWR snapshots.)
But what if the SQL ceases to be that colorful—that is, not important enough to be captured? You can turn it off by issuing the obverse of the procedure.
begin
dbms_workload_repository.remove_colored_sql(
sql_id => 'ff15115dvgukr'
);
end;
This feature is extremely useful when you want to focus on a specific SQL in your tuning exercises.
OLTP Table Compression
Compression has been an Oracle Database feature in one form or other for a long period
Compression is always CPU-intensive and it takes time. Usually, if you compress data, it has to be uncompressed to be usable. While this requirement is acceptable in data warehouse environments, where the SQL typically operates on a large number of rows and large response times are generally tolerable, it may not be acceptable on OLTP environments.
Now, in Oracle Database 11g, you can do this:
create table my_compressed_table (
col1 number(20),
col2 varchar2(300),
...
)
compress for all operations
The clause "compress for all operations" enables compression on all DML activities like INSERT, UPDATE, etc. The compression occurs on all DML activities; not just direct path inserts as in the previous versions.
Will that slow the DML? Not necessarily. This is where the new feature works best. The compression does not occur when the row is inserted into the table. Instead, the rows are inserted uncompressed and in the routine way. When a certain number of rows are inserted (or updated) in the uncompressed manner, the compression algorithm kicks in and compresses all the uncompressed rows in the block. In other words, the block is compressed, not the row. The threshold at which the compression occurs is internally defined inside the RDBMS code.
Mechanics of Compression
Consider a table, ACCOUNTS, with records shown below:

Inside the database, assume a single database block has all the above rows.

This is what an uncompressed block looks like: with the records with all the data in all the fields (columns). When this block is compressed, the database first calculates the repeating values found in all the rows, moves them out of the rows, and puts them near the header of the block. These repeating values in the rows are replaced with a symbol that represents each of these values. Conceptually it is shown in the figure below where you can see a block before and after compression.

Note how the values have been taken out of the rows and put in a special area at the top called "Symbol Table". Each value in the columns is assigned a symbol that takes the place of the actual value inside the rows. As symbols are smaller than the actual values, the record sizes are considerably smaller than the original as well. The more repeating data the row has, the more compact the symbol table and subsequently the block.
Because compression occurs as a triggered event, not when the row is inserted, the performance impact of the compression is nil during the normal DML process. When the compression is triggered, the demand on the CPU becomes high, of course,but at all other times the CPU impact is zero, making the compression suitable for OLTP applications as well—which is the sweetspot for compression in Oracle Database 11g.
Apart from reduced space consumption, the compressed data takes less time to go across the network, uses less space for backup, and makes it feasible to maintain full copies of the production database in QA and testing.
COPY is Undead!
Contrary to the rumors, the COPY command is still around. And it is still the only way to copy LONG datatypes. But as it has been made deprecated, it has not kept pace with the newer developments in Oracle Database.
For instance, it does not know about the presence of a new datatype called BFILE. If you try to copy the table DOCS, which has a column as BFILE shown in the earlier example:
SQL> copy to sh@oradba11 -
> replace docs_may08 -
> using select * from docs
> where creation_dt between '1-may-08' and '31-may-08';
Enter TO password:
Array fetch/bind size is 15. (arraysize is 15)
Will commit when done. (copycommit is 0)
Maximum long size is 80. (long is 80)
CPY-0012: Datatype cannot be copied
The error message says it all: the COPY command can't copy the BFILE datatype. But in the case of a table with a LONG column, you can't use INSERT /*+ APPEND */ and CREATE TABLE ... NOLOGGING AS SELECT ... statements. Here is an example where we are trying to copy some rows from one table to another where there is a column defined as LONG:
SQL>create table mytab1 as select * from mytab where col1 = 'A';
create table mytab1 as select * from mytab
*
ERROR at line 1:
ORA-00997: illegal use of LONG datatype
SQL> insert /*+ APPEND */ into mytab
2> select * from mytab where col1 = 'A';
select * from mytab
*
ERROR at line 2:
ORA-00997: illegal use of LONG datatype
So, your only easy option to copy a large amount of data without filling up the undo segments is to use the COPY command.
Exports and Import: Hanging by a Thread
When Data Pump was introduced in Oracle Database 10g, the eventual obsolescence of the traditional Export and Import tools were expected. Well, keep waiting: in Oracle Database 11g, these old tools are very much there. Being deprecated, they no longer receive any more enhancements, but they are far from useless.
In terms of features Data Pump outdoes the Regular Export/Import many times over but in one simple case the latter is still immensely useful: when you have to create a dump file on the client and not the server. There is no need to create a directory before performing the operations, so in many ways a simple data export is probably easier through the Regular Export/Import.
But, again, these tools are deprecated, so there are three risks to using them:
- Oracle will not add any functionality to them so future datatypes, etc. may not be supported.
- They may disappear from a future release without advanced warning, forcing you to rewrite the code later.
- If you encounter a bug, Oracle Support may refuse to fix that code.
So, it may be worthwhile to convert existing code to Data Pump, and definitely so for new developments.
Incrementally Updated Global Statistics
In partitioned tables, each partition can have optimizer statistics. In addition, there is a global statistic on the entire table that is not partition dependent—the number of distinct values across the table, for example. This global statistic is collected only when instructed in the dbms_stats.gather_*_stats procedures; not by default. If the global stats parameter is not specified, they are not collected and the optimizer derives them from the partition stats. Of course, the calculated global stats are always more accurate than the derived ones so it's always advisable to collect them.
But there used to be a little problem:. When a partition data changes but other partitions remain unchanged, the global stats might become stale. Thus the stats collection program had to go through the entire table to collect the global stats even though only one partition has a change.
Not so anymore. In Oracle Database 11g, you can instruct the optimizer to collect the global stats incrementally from the changed partition alone, not by doing another full table scan. This is done by setting a table parameter for stats collection—INCREMENTAL—to TRUE, as shown below:
begin
dbms_stats.set_table_prefs(
'SH','SALES','INCREMENTAL','TRUE');
end;
/
Now you should collect the stats on this table, and specifically the partition SALES_1995, with a granularity of AUTO.
begin
dbms_stats.gather_table_stats (
ownname => 'SH',
tabname => 'SALES',
partname => 'SALES_1995',
granularity => 'AUTO'
);
end;
This method of stats collection instructs the database to incrementally update the global stats from those collected from the new partition.
Data Pump Gets Better
As I mentioned previously, Data Pump has been the tool of choice for moving large amounts of data, or for taking "logical" backups of the data efficiently, since the previous release. Similar to Export/Import, it's platform independent (for instance you can export from Linux to import into Solaris). It got a few enhancements in Oracle Database 11g.
One of the big issues with Data Pump was that the dumpfile couldn't be compressed while getting created. That was something easily done in the older Export/Import utility. In Oracle Database 11g, Data Pump can compress the dumpfiles while creating them. This is done via a parameter COMPRESSION in the expdp command line. The parameter has three options:
- METDATA_ONLY - only the metadata is compressed; the data is left as it is (available in Oracle Database 10.2 as well).
- DATA_ONLY - only the data is compressed; the metadata is left alone.
- ALL - both the metadata and data are compressed.
- NONE - this is the default; no compression is performed.
Here is how you compress the export of the table UNITS_FACT:
$ expdp global/global directory=dump_dir tables=units_fact dumpfile=units_fact_comp.dmp compression=all
For comparison purposes, export without compression:
$ expdp global/global directory=dump_dir tables=units_fact dumpfile=units_fact_uncomp.dmp
Now if you check the files created:
$ ls -l
-rw-r----- 1 oracle dba 2576384 Jul 6 22:39 units_fact_comp.dmp
-rw-r----- 1 oracle dba 15728640 Jul 6 22:36 units_fact_uncomp.dmp
The compression ratio is 100*(15728640-2576384)/15728640 or about 83.61%! That's fairly impressive; the uncompressed dumpfile is 15MB while the compressed one is 1.5MB.
If you compress the dumpfile using gzip:
$ gzip units_factl_uncomp.dmp
-rw-r----- 1 oracle dba 3337043 Jul 6 22:36 units_fact_uncomp.dmp.gz
The compressed file is about 3.2MB, double the size of the compressed file in Data Pump. So, in addition to the compression being potentially more efficient, the decompression really adds value. When importing the dumpfile, the import does not have to decompress the file first; it decompresses as it reads it, making the process really fast.
The two other enhancements in Data Pump are:
- Encryption: the dumpfile can be encrypted while getting created. The encryption uses the same technology as TDE (Transparent Data Encryption) and uses the wallet to store the master key. This encryption occurs on the entire dumpfile, not just on the encrypted columns as it was in the case of Oracle Database 10g.
- Masking: when you import data from production to QA, you may want to make sure sensitive data such as social security number, etc. are obfuscated (altered in such a way that they are not identifiable). Data Pump in Oracle Database 11g enables you do that by creating a masking function and then using that during import.
You can read about both these features in the security installment.
Truly Online Index Rebuild
Remember the ONLINE clause while rebuilding an index?
alter index in_tab_01 rebuild online;
The clause rebuilds the index without affecting the DML accessing it. It does so by tracking which blocks are being accessed and at the end merging these blocks with the newly built index. To accomplish this task the operation had to get an exclusive lock at the end of the process. Although short in duration, it was a lock nevertheless, and DMLs had to wait.
In Oracle Database 11g, the online rebuild is truly online: it does not hold an exclusive lock. The DMLs are not affected.
Different Tablespace for Temporary Tables
When you create a global temporary table, where does the allocation come from for the space occupied? It comes from the user's temporary tablespace. Usually this is not going to be an issue, but in some special cases, you may want to free up the temporary tablespace for the purpose it is supposed to be for (sorting, mostly). Sometimes you may want create the temporary tables to use another temporary tablespace on faster, more efficient disks to make the data access faster. In those cases you had no choice but to make that tablespace the user's temporary tablespace.
In Oracle Database 11g you can use another temporary tablespace for your global temporary tables. Let's see how. First you create another temporary tablespace:
SQL> create temporary tablespace etl_temp
2> tempfile '+DG1/etl_temp_01.dbf'
3> size 1G;
Tablespace created.
Then, you create the GTT with a new tablespace clause:
SQL> create global temporary table data_load (
2> input_line varchar2 (2000)
3> )
4> on commit preserve rows
5> tablespace etl_temp;
Table created.
This temporary table is now created on tablespace etl_temp instead of the user's default temporary tablespace—TEMP.
SQL*Plus Error Logging
Suppose you have a SQL script called myscript.sql:
set puase on
set lines 132 pages 0 trimsppol on
select * from nonexistent_table
/
Note there are several errors in the script: the first line has "pause" misspelled, the second line has "trimspool" misspelled, and finally the third line has a select statement from a table that does not even exist. When you run the script via SQL*Plus prompt, unless you spooled the output, you will not be able to check the error afterward. Even if you spooled, you would have access to the physical server to examine the spool file, which may not be possible.
Oracle Database 11g has a perfect solution: Now you can log the errors coming from SQL*Plus on a special table. You should issue, as a first command:
SQL> set errorlogging on
Now you run the script:
SQL> @myscript
The run will produce the following error messages:
SP2-0158: unknown SET option "puase"
SP2-0158: unknown SET option "trimsppol"
select * from nonexistent_table
*
ERROR at line 1:
ORA-00942: table or view does not exist
which you may or may not have seen, depending on how you ran the script—in the foreground from an SQL*Plus prompt or in the background as a script invocation. After the script completes, you can log into the database and check the errors in a table named SPERRORLOG.
sql> col timestamp format a15
sql> col username format a15
sql> col script format a10
sql> col identifier format a15
sql> col statement format a20
sql> col message format a20
sql> select timestamp, username, script, statement, message
2> from sperrorlog;
TIMESTAMP USERNAME SCRIPT STATEMENT MESSAGE
--------------- --------------- ---------- -------------------- --------------------
05-JUL-08 06.08 SH myscript.s set puase on SP2-0158: unknown SE
.41.000000 PM ql T option "puase"
05-JUL-08 06.08 SH myscript.s set lines 132 pages SP2-0158: unknown SE
.41.000000 PM ql 0 trimsppol on T option "trimsppol"
05-JUL-08 06.08 SH myscript.s select * from nonexi ORA-00942: table or
.41.000000 PM ql stent_table view does not exist
Note that you checked the error from a different session, not the session where the script was run. In fact the script has finished and the session has been terminated anyway. This gives you a powerful ability to check errors after they occurred in SQL*Plus sessions that were impossible, or at least difficult, to track otherwise.
The table SPERRORLOG is a special table that is created for this purpose only. You can also create your own table and populate that with errors from SQL*Plus. This table should be created as:
SQL> create table my_sperror_log
2 (
3 username varchar2(256),
4 timestamp timestamp,
5 script varchar2(1024),
6 identifier varchar(256),
7 message clob,
8 statement clob
9 )
10 /
Table created.
Now you can use this table in error logging instead of the default table.
SQL> set errorlogging on table sh.my_sperror_log;
SQL> @myscript
Now MY_ERROR_LOG (and not SPERRORLOG) will hold the error log. You can truncate all the rows in the table by issuing
SQL> set errorlogging on truncate
There is an optional IDENTIFIER clause that allows you to tag the errors from specific sessions. Suppose you issue the command:
SQL> set errorlogging on identifier MYSESSION1
Now if you run the script, the records will be created with the column called IDENTIFIER populated with the value MYSESSION1. You can extract those records only by issuing the query:
select timestamp, username, script, statement, message
from sperrorlog
where identifier = 'MYSESSION1';
You will see the records from that session only. This is very useful if you are trying to isolate errors in multiple scripts and sessions.
Shrinking the Temporary Tablespace
You probably already know that temporary tablespaces are special; normal rules of space management may not apply to them. When a temporary segment is allocated, it is not deallocated. This is not really a problem, since the temporary segments (which are what the temporary tablespaces are for) are not part of the schema and are not stored across database recycles. The space is reused for another user or another query. Anyway, since the space is not deallocated, the temporary tablespaces just keep growing. But what if you want to trim them to make room for other tablespaces?
Until now the only option was to drop and recreate the tablespace—a rather trivial task that can be done almost always online. However there is a little "but": What if you can't afford to accept anything other than 100-percent uptime? In Oracle Database 11g, you can easily do that, by shrinking the temporary tablespace.
Here is how the tablespace TEMP1 is shrunk:
alter tablespace temp1 shrink space;
This deallocates all the unused segments from the tablespace and shrinks it. After the above operation, you can check the view DBA_TEMP_FREE_SPACE to check how much the allocated space and free space currently is.
SQL> select * from dba_temp_free_space;
TABLESPACE_NAME TABLESPACE_SIZE ALLOCATED_SPACE FREE_SPACE
------------------------------ --------------- --------------- ----------
TEMP 179306496 179306496 178257920
In a relatively quiet database the shrink operation might shrink the temporary tablespace to almost empty. You know that's just artificial; as the subsequent activities will expand the tablespace, you might want to leave some space inside, say 100MB. You can do it as follows:
SQL> alter tablespace temp shrink space keep 100m;
Tablespace altered.
SQL> select * from dba_temp_free_space;
TABLESPACE_NAME TABLESPACE_SIZE ALLOCATED_SPACE FREE_SPACE
------------------------------ --------------- --------------- ----------
TEMP 105906176 1048576 104857600
All the space but 100MB was released. This approach helps you manage the space in various tablespaces. Now you can borrow the space from inside a temporary tablespace to give to other tablespace temporarily (no pun intended). Later when that space is no longer needed, you can give it back to the temporary tablespace. When you combine this feature with the tablespace for global temporary tables you can resolve many difficult space management issues in temporary tablespaces.
SQL*Plus Shows BFILE
The datatype BFILE in Oracle Database stores the pointer to an external file, not the contents of the file itself. It serves a specific purpose: the database space is conserved while the users have access to the data in the files, which is great for some applications such as ones using content and multi-media rich databases.
If you have a column with BFILE in a table and you want to select the rows of the tale in SQL*Plus, you used to get an error. In Oracle Database 11g, SQL*Plus shows you the location of the file as a value in the column.
Let's see an example. First you have to create a directory to store the BFILE.
SQL> create directory doc_dir as '/u01/oracle/docs';
Directory created.
Now, create the table.
SQL> create table docs
2 (
3 doc_id number(20),
4 doc_file bfile,
5 doc_type varchar2(10)
6 );
Table created.
Create the row.
SQL> insert into docs values
2 (
3 1,
4 bfilename('DOC_DIR','metric_daily_report.pdf'),
5 'PDF'
6 );
1 row created.
Now if you select this row in SQL*Plus:
SQL> col doc_file format a50
SQL> select * from docs;
DOC_ID DOC_FILE DOC_TYPE
---------- -------------------------------------------------- ----------
1 bfilename('DOC_DIR', 'metric_daily_report.pdf') PDF
The output under the column DOC_FILE, which is a BFILE, shows the location of the file instead of erroring out.
Parameter Files from Memory
Consider this scenario: in the course of diagnosing some database issue, you modified a lot of parameters, all in memory. Later you forget which parameters you changed. Unless you remembered to put these parameters in the initialization parameter file (pfile or spfile), these changes will be lost. Most likely you didn't put them there as you were experimenting with the values and weren't sure which specific value to use. Of course, you can go through the alert log and pick out all the changes made—a procedure not only painful but error-prone as well.
In Oracle Database 11g, you can use a very simple command to create a pfile or an spfile from the parameter values from memory.
SQL> create spfile from memory;
File created.
SQL> create pfile from memory;
File created.
This will create an spfile or pfile with the values from the memory. The pfile will have an entry at the top of the file like this:
# Oracle init.ora parameter file generated by instance ODEL11 on 08/28/2007 14:52:14
This saves you a lot or effort and risk in capturing the parameters changed in the memory. This feature also allows you to create a pfile in another name and then compare the current pfile to this generated one to see which parameters were changed.
SQL> create pfile='/tmp/a' from memory;
This statement creates the pfile as /tmp/a. Now in unix, you can use the simple diff command to show the differences in these two files.
Reset with Care
In course of a performance tuning process you are examining the impact of changing several dynamic initialization parameters directly on the spfile, and suddenly you are concerned that you have lost track of what you changed. Since these are changed in the spfile, you can't count on the spfile to tell you what values you changed.
Well, here comes the cavalry: The ALTER SYSTEM RESET command resets the value to the default value, overriding what you have the spfile:
alter system reset license_max_sessions;
This command was available in earlier releases as well but with one fundamental difference: it required a SID clause earlier in RAC databases. If you wanted to reset it on all instances, you would have specified SID='*' clause. In Oracle Database 11g, the SID clause is optional and the default is all instances. So, if you omit the clause, it would have errorred out earlier; now it succeeds, but the effect may not be what you wanted. So, watch out.
Real-time SQL Monitoring
Performance diagnosis takes a giant leap with this feature. Consider this: someone is running a bunch of SQL (perhaps inside a PL/SQL code). How do you know how much resource (CPU, I/O, etc.) each step of the access path is taking? You can trace the session or analyze the tracefile using Trace Analyzer or the plain old tkprof, but that's after the fact. You would have loved to get a real time window into what's going in the session, wouldn't you?
In Oracle Database 11g, a new feature, Real-time SQL Monitoring, does exactly what the name implies: it allows you to see the different metrics of the SQL being executed in real time. The stats are exposed through the dynamic performance view V$SQL_MONITOR, which is refreshed every second.
To demonstrate, let's run a large query and monitor the real time stats. We know that the SID of the session running the large query is 103. While selecting from the view I have used Tom Kyte's famous print_table tool ,which displays the output in the vertical format for better readability.
SQL> exec print.tbl('select * from v$sql_monitor where sid = 103')
KEY : 476741369968
STATUS : EXECUTING
FIRST_REFRESH_TIME : 07-jul-2008 14:13:38
LAST_REFRESH_TIME : 07-jul-2008 14:26:27
REFRESH_COUNT : 48043
SID : 103
PROCESS_NAME : ora
SQL_ID : 2xj1nram1k1x0
SQL_EXEC_START : 07-jul-2008 14:13:31
SQL_EXEC_ID : 16777216
SQL_PLAN_HASH_VALUE : 1759042790
SQL_CHILD_ADDRESS : 38837734
SESSION_SERIAL# : 32668
PX_SERVER# :
PX_SERVER_GROUP :
PX_SERVER_SET :
PX_QCINST_ID :
PX_QCSID :
ELAPSED_TIME : 42638722
CPU_TIME : 9199624
FETCHES : 48032
BUFFER_GETS : 3238
DISK_READS : 12096
DIRECT_WRITES : 13419
APPLICATION_WAIT_TIME : 0
CONCURRENCY_WAIT_TIME : 134534
CLUSTER_WAIT_TIME : 0
USER_IO_WAIT_TIME : 148436
PLSQL_EXEC_TIME : 0
JAVA_EXEC_TIME : 0
-----------------
Most of the columns are self explanatory: SQL_ID—the sql_id of the SQL statement being executed by the SID; STATUS—the status of the SQL right now, which shows that it's being executed right now; SQL_EXEC_START—the time it started; and so on. The columns such as CPU_TIME, DISK_READS and DIRECT_WRITES show their namesake metrics. If you keep on executing the query, you will see these metrics getting updated.
Another view ,V$SQL_PLAN_MONITOR, shows the optimizer plan of the SQL statement executed updated in real time. Here is how you can use the view to see the various steps in the plan and the associated stats in real time.
select plan_line_id,
plan_operation,
plan_options,
output_rows
from v$sql_plan_monitor
where sid = 103
order by plan_line_id;
PLAN_LINE_ID PLAN_OPERATION PLAN_OPTIONS OUTPUT_ROWS
------------ ------------------------------ ------------------------------ -----------
0 SELECT STATEMENT 809994
1 HASH GROUP BY 809994
2 HASH JOIN 918845
3 PART JOIN FILTER CREATE 1826
4 TABLE ACCESS FULL 1826
5 HASH JOIN 918845
6 TABLE ACCESS FULL 503
7 HASH JOIN 918845
8 TABLE ACCESS FULL 72
9 HASH JOIN 918845
10 TABLE ACCESS FULL 5
11 HASH JOIN 918845
12 TABLE ACCESS FULL 55500
13 PARTITION RANGE JOIN-FILTER 918845
14 TABLE ACCESS FULL 918845
Like the previous view, if you re-execute the query you will see the metrics getting updated. These two views allow you to peek into the processing for that SQL in real time.
Another useful part of the real time SQL monitoring is the SQL Monitor Report. Using this report, you can get a visual report of various metrics on the SQL and the plan steps. This report is generated as a CLOB output from the function REPORT_SQL_MONITOR in the package DBMS_SQLTUNE. Here is how you invoke that function:
SQL> set long 99999 lines 3000 pages 0 trimspool on
SQL> select dbms_sqltune.report_sql_monitor (
2 event_detail => 'YES',
3 report_level => 'ALL',
4 type => 'HTML'
5 )
6 from dual;
Spool the output to a file named rep1.html and run the SQL. After a few moments, run this SQL again spooling to a new file - rep2.html. Finally, run it after the query completes spooling to rep3.html. Each report file is a snapshot of SQL real time metrics as of that time. Taking the report at three different times allows you to track the progress. Open up one of the files in a Web browser, shown below:

Here you see the SQL statement whose metrics are being displayed. On the top left you can see the metadata about the SQL—the time it started, last refresh time, etc. To the right of that you see different colored bars representing the various metrics. If you hover your mouse over these bars you will see the description of that as well as the value it illustrates.
The lower part of the screen shows the optimizer plan for the query and the time taken in each step, under categories such as CPU activity, Waits, and so on. Colored bars show the relative values of each metric. If you hover your mouse above those bars you will see the values and time periods for each metric.
This report is nothing but a snapshot of the real-time SQL monitor view you saw earlier presented in a graphical format. The data, presented graphically, helps you understand the components of the query and measuring the times spent in each of them, making performance diagnosis far easier.
End Note
This concludes the 20-week-long, whirlwind tour of the new features introduced in Oracle Database 11g. Like any author, I struggled to maintain the delicate balance between depth and breadth. But in the previous article series on Oracle Database 10g Rel 1 and Rel 2, your feedback was loud and clear: you loved the example-based story telling approach, so I did not stray from that format in this series.
My sincere appreciation goes out to the reviewers who validated this series. I couldn't thank Justin Kestelyn enough, for the support and the help in making this project a success. And, thank you, dear reader, for making it all worthwhile.
Back to "Oracle Database 11g: Top Features for DBAs and Developers" homepage
Arup Nanda (arup@proligence.com) has been exclusively an Oracle DBA for more than 12 years with experiences spanning all areas of Oracle Database technology, and was named "DBA of the Year" by Oracle Magazine in 2003. Arup is a frequent speaker and writer in Oracle-related events and journals and an Oracle ACE Director. He co-authored four books, including RMAN Recipes for Oracle Database 11g: A Problem Solution Approach.
|