Dec 14, 2017

10 points may not be used by Oracle DBA

1) ORADEBUG SUSPEND | RESUME | WAKEUP

SUSPEND command:
This command suspends the current process. First select a process using SETORAPID or SETOSPID
Do not use SETMYPID as the current ORADEBUG process will hang and cannot be resumed even from another ORADEBUG process.

e.g.,
ORADEBUG SUSPEND

RESUME command:
resumes the current process.
While the process is suspended ORADEBUG can be used to take dumps of the current process state e.g. global area, heap, subheaps etc.

e.g.,
ORADEBUG RESUME

WAKEUP command
To wake up a process use:

ORADEBUG WAKEUP pid

For example to wake up SMON, first obtain the PID using:
SELECT pid FROM v$process
WHERE addr =
(
    SELECT paddr FROM v$bgprocess
    WHERE name = 'SMON'
);

If the PID is 6 then send a wakeup call using:
ORADEBUG WAKEUP 6

e.g.,
Suspend a running process
SQL> oradebug setorapid 12
Unix process pid: 10131, image: oracle@localhost.localdomain (TNS V1-V3)
SQL> oradebug suspend
Statement processed.

Resume a process
SQL> oradebug resume
Statement processed.

If you have trace turned on a suspended and resume session you will see the following messages in the trace file.
....
FETCH #5:c=54992,e=55962,p=0,cr=2334,cu=0,mis=0,r=1,dep=1,og=1,tim=1249098751175228
EXEC #5:c=0,e=72,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=1,tim=1249098751175408
Received ORADEBUG command ‘suspend’ from process Unix process pid: 22990, image:
*** 2017-12-14 21:12:34.268
Received ORADEBUG command ‘resume’ from process Unix process pid: 22990, image:
FETCH #5:c=58991,e=32316703,p=0,cr=2334,cu=0,mis=0,r=1,dep=1,og=1,tim=1249098783492125
EXEC #5:c=0,e=71,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=1,tim=1249098783492321
....

3) SQL Full Text: Which view I will use? v$sql | v$sqlarea | v$sqlstats

The column definition for columns in V$SQLSTATS are identical to those in the V$SQL and V$SQLAREA views. However, the V$SQLSTATS view differ from V$SQL and V$SQLAREA in that it is faster, more scalable, and has a greater data retention (the statistics may still appear in the view, even after the cursor has been aged out of the shared pool).

3) DESC command can be used inside SQL query to view dynamic result instead of cancel the whole query and re-write:

e.g.,
SQL> select TABLE_NAME,INDEX_NAME,LAST_ANALYZED
  2  from dba_indexes
  3  where
  4  #desc dba_indexes
 Name                                                              Null?    Type
 ----------------------------------------------------------------- -------- --------------------------------------------
 OWNER                                                             NOT NULL VARCHAR2(128)
 INDEX_NAME                                                        NOT NULL VARCHAR2(128)
 INDEX_TYPE                                                                 VARCHAR2(27)
 TABLE_OWNER                                                       NOT NULL VARCHAR2(128)
 TABLE_NAME                                                        NOT NULL VARCHAR2(128)
 TABLE_TYPE                                                                 VARCHAR2(11)
 LAST_ANALYZED                                                              DATE
 DEGREE                                                                     VARCHAR2(40)

  4  OWNER='SCOTT';

TABLE_NAME                    INDEX_NAME                                    LAST_ANALYZED
EMP                                       empid_pk                                           07-MAR-17
DEPT                                      deptno_pk                                         07-MAR-17
…..                                         
SQL>

4) Transaction commit when exiting SQL*Plus

if the case of exit without commit from sqlplus, the running transaction commit or rollback??
Answer will be Yes|no. It depends upon what the exitcommit parameter is set to!

To see current setting:
e.g.,
SQL> sho exitcommit
exitcommit ON                  (default)

To OFF:
SET EXITCOMMIT OFF;  ( this makes you “rollback” on exit)


5) Estimating Cardinalities using GATHER_PLAN_STATISTICS hint ( Oracle 10g & above)

If we add the GATHER_PLAN_STATISTICS hint to our simple SQL statement we should be able to see the actual cardinality of each operation at execution time alongside the Optimizer estimates for each cardinality in the plan.
e.g.,
SELECT     /*+ GATHER_PLAN_STATISTICS */ p.prod_name, SUM(s.quantity_sold)
FROM       sales s, products p
WHERE      s.prod_id =p.prod_id
AND        p.prod_desc = 'Consumables'
GROUP By p.prod_name ;
…..
SQL> SELECT *
FROM table(DBMS_XPLAN.DISPLAY_CURSOR(FORMAT=>'ALLSTATS LAST'));



The FORMAT parameter value 'ALLSTATS LAST' requests that the execution statistics of the last execution of the cursor be shown.

In order to see the A-Rows values for all of the operations in the plan you would have to use the FORMAT value  'ALLSTATS ALL', which will show you the execution statistics for ALL executions of the cursor. Be careful here as the values in the A-Rows column is now cumulative (incremented on every execution). The more the statement is executed the higher the values in the A-Rows column will become. This FORMAT will also show you a lot more columns in the execution plan.

6. Create index with COMPRESS:

People have often commented to me that Table Compression (and Advanced Row Compression) are  great at helping to reduce the storage footprint of an Oracle database by a factor of 2x-5x, but Oracle shouldn’t forget about the indexes.

In my experience, indexes often take up to 50% of the total database space and it is not uncommon to have 10-20 indexes on a single table (in extreme cases, It may 100 indexes per table).

Syntax:
CREATE INDEX idx_name ON table_name(col1, col2, col3) COMPRESS [<prefix_col_length>] ;

e.g.,
create index idx_test product(product_type,product_color,manufacture_date) compress 2;

The <prefix_col_length> after the COMPRESS keyword denotes how many columns to compress. The default (and the maximum) prefix length for a non-unique index is the number of key columns, and the maximum prefix length for a unique index is the number of key columns minus one.

Prior to Oracle 11g, it is risk if prefix columns are defined properly. You may have following issues:
a)       there is a small CPU overhead to reconstruct the key column values during index lookup or scans
b)      running ANALYZE INDEX takes an exclusive lock on the table, effectively making the table “offline” for this period
c)       Not useful if prefix columns are unique in a block
d)      You cannot compress your Functional Indexes with Advanced Index Compression.
e)      Bitmap indexes can't be compressed.


On partition Table:
CREATE INDEX my_test_idx ON test(a, b) COMPRESS ADVANCED LOW local
    (PARTITION p1 COMPRESS ADVANCED LOW,
     PARTITION p2 COMPRESS,
     PARTITION p3,
 PARTITION p4 NOCOMPRESS);

7. _use_nosegment_indexes parameter and nosegment keyword:

In contrast to conventional indexes, a virtual index has no associated segment, so the creation time and associated disk space are irrelevant. In addition, it is not seen by other sessions, so it doesn't affect the normal running of your system. This article presents a simple example of how virtual indexes are used.

A virtual index is a "fake" index whose definition exists in the data dictionary, but has no index tress association.  It is used by Oracle developers to test whether a specific index is going to use useful without having to use the disk space associated with the "real" index.  The hidden parameter _use_nosegment_indexes is used by Quest tools and is also use in the Oracle Tuning pack.

Because the virtual index is a fake index, Oracle will never be able to use it, but you can use the hidden _use_nosegment_indexes parameter to evaluate execution plans for virtual indexes:

SQL> set autotrace on explain;
SQL> alter session set "_use_nosegment_indexes" = true;
Session altered.
SQL> select ename from emp where ename = 'MILLER';

ENAME
-----
MILLER

1 rows selected.

OBJECT     OPERATION
---------- ----------------------------------------
                 SELECT STATEMENT()
                  NESTED LOOPS()
EMP                TABLE ACCESS(FULL)
EMP                 TABLE ACCESS(BY INDEX ROWID)
VIRTUAL_INDEX         INDEX(UNIQUE SCAN)

Creating virtual indexes:

The CREATE INDEX statement has a special hidden "nosegment" clause that allows one to create an index definition without actually creating the index.

To build a virtual index, runs the following statement:

CREATE unique INDEX virt_ind_name on table_name(col_name) NOSEGMENT;

Removing virtual indexes:

It is important to drop the index after you're done with it.
e.g.,
DROP INDEX virt_ind_name;

8. Create Tigger with DISABLE : (Oracle 11g onwards)

Prior to Oracle 11g, disabling triggers used to be a two step process. Triggers were automatically created in an ‘enabled’ state. To disable it we had to disable it using the DISABLE clause of the ‘ALTER TRIGGER’ or ‘ALTER TABLE ‘ commands.

In Oracle 11g, we can specify ‘DISABLE’ clause in trigger definition it self.  In the absence of the ‘DISABLE’ clause, the trigger is created in an ‘ENABLED’ state. Following is the script to create table and then create trigger in disabled state.

CREATE TABLE TEST
(
COL1 VARCHAR(5) NOT NULL,
COL2 NUMBER(5),
COL3 DATE
);

Let us create a trigger now.

CREATE OR REPLACE TRIGGER TRI_TEST
BEFORE INSERT ON TEST
FOR EACH ROW
DISABLE
BEGIN
:NEW.COL3 := SYSDATE;
END;

Trigger will be created successfully.  We can verify the status of the trigger using data dictionary view user_triggers. Even though trigger is created in a disabled status,  Oracle will make sure that it does not have any compilation errors. Trigger will be compiled with errors if we try to reference non-existent column in the trigger.

This feature can be very useful when we want to enable trigger at later stage for a specific events and as mentioned earlier, we can avoid extra step of altering the trigger after creation.

9. Export direct =y ( EXPDP direct=y …)

The speedup of the direct path export can be large however. The 10% of the processing that it cuts out, accounts for a much larger percentage of the run-time. For example, I have just exported about 100meg of data, and 1.2 million records. The direct path export took about one minute. The conventional path export on the other hand took three minutes.

Setting direct=true bypasses the SGA, so it will be faster. Help full in case mission critical/ OLTPs environments.

10. 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;

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.


No comments:

Post a Comment

Translate >>