tuning tips ppt[1]

Download Tuning Tips Ppt[1]

If you can't read please download the document

Upload: sriharsha-majjiga

Post on 28-Nov-2015

30 views

Category:

Documents


2 download

DESCRIPTION

oracle tuning tips

TRANSCRIPT

Tuning Tips and Techniques

SQL Performance Tuning Tips

Tuning Tips and Techniques

Oracles SQL is a very flexible language. You can use many different SQL statements to accomplish the same purpose.

Yet, although dozens of differently constructed queries and retrieval statements can produce the same result, in a given situation only one statement will be the most efficient choice.

It is much harder to write efficient SQL than it is to write functionally correct SQL

A SQL choice is correct only if it produces the right result in the shortest possible amount of time, without impeding the performance of any other system resources.

Sharing SQL Statements

Parsing a SQL statement and figuring out its optimal execution plan are time-consuming operations, Oracle holds SQL statements in memory after it has parsed them

Whenever you issue a SQL statement, Oracle first looks in the context (SGA) area to see if there is an identical statement there

To be shared, the SQL statements must truly be the same

For example the following two select statements are NOT the same:

SELECT STUDENT_NMBER,

NAME

FROM STUDENT

WHERE STUDEN_NUMBER =0220

Select Student_Number,

Name

From Student

Where Student_Number = 0220

Using Bind variables when possible

Try using Bind Variable instead of Literals. Consider the following SQL statement

SELECT FIRST_NAME, LAST_NAME

FROM Client

WHERE CLIENT_NUM = 1200

Since the CLIENT_NUMBER is likely to be different for every execution, we will almost never find a matching statement in the Shared Pool and consequently the statement will have to be reparsed every time

Consider the following approach

SELECT FIRST_NAME, LAST_NAME

FROM Client

WHERE CLIENT_NUM =:Client_Num

You do not need to create a new cursor or re-parse the SQL statement if the value of the bind variable changes. Also, if another session executes the same statement, it is likely to find them in the Shared Pool, since the name of the bind variable does not change from execution to execution.

Using ROWID When Possible

Each record added to the database has a unique ROWID and will never change until the delete statement issued on that record.

If the record block or location was changed for any reason, the original ROWID points to the new location or the new ROWID and so on.

Use ROWID whenever possible to get the best performance out of your retrievals

cursor accounts_cur is

select acct_no,

currency,

branch

Rowid acct_rowid,

From account

where . . . .

for acct_rec in accounts_cur loop

update account set

where rowid =acct_rec.acct_rowid;

end loop;

Using WHERE in Place of HAVING

In general, avoid including a HAVING clause in the SELECT statements. The HAVING clause filters selected rows only after all rows have been fetched. This could include sorting, summing, and etc. HAVING clause

usually used to filter a SELECT statement containinggroup functions.

select *

from account

where cust_Active_flag =y

having group =001

Instead use -

select *

from account

where cust_Active_flag =y

and group =001

Using UNION ALL instead of UNION

The SORT operation is very expensive in terms of CPU consumption.

The UNION operation sorts the result set to eliminate any rows, which are within the sub-queries.

UNION ALL includes duplicate rows and does not require a sort. Unless you require that these duplicate rows be eliminated, use UNION ALL

Using NOT EXISTS in place of NOT IN for indexed columns

In sub-query statements such as the following, the NOT IN clause causes an internal sort/merge.

select * from Student

where STUDENT_NUM not in

(select STUDENT_NUM from CLASS)

So use-

select * from STUDENT C

where not exists

(select 1 from CLASS A where A.STUDENT_NUM = C.STUDENT_NUM)

Using IN with MINUS in place of NOT IN for non indexed columns

In sub-query statements such as the following, the NOT IN clause causes an internal sort/merge

select * from system_user

where su_user_id not in

(select ac_user from account)

INSTEAD USE

select * from system_user

where su_user_id in

(select su_user_id from system_user

minus

select ac_user from account)

Using Joints in Place of EXISTS for Unique Scan Indexes and small tables

In general join tables rather than specifying sub-queries for them such as the following:

select acct_ID, currency, branch

from account

where exists (select 1 from branch where code = branch and def_curr = '001')

With join -

select acct_ID,currency, branch

from account A, branch B

where b.code = A.branch

and A.def_curr = '001'

Influencing the Optimizer using HINTS

Hints are special instructions to Optimizer. You can change the Optimization goal for an individual statement by using Hint. Some commonly used Hints are: CHOOSE, RULE, FULL(table_name), INDEX(table_name index_name), USE_NL, USE_HASH(table_name), PARALLEL(table_name parallelism) etc.

SELECT /*+RULE*/ NAME,

ACCT_ALLOCATION_PERCENTAGE

FROM ACCOUNTS WHERE ACCOUNT_ID = 1200

The above SQL statement will be processed using the RULE based optimizer.

SELECT/*+ INDEX(A, ACCT_ID_IND) */NAME,

ACCT_ALLOCATION_PERCENTAGE

FROM ACCOUNTS A

WHERE ACCOUNT_ID =:ACCT_IDAND CLIENT_ID=:CLIENT_ID

In the above SQL statement, an Index Hint has been used to force the use of a particular index.

Using Indexes to Improve Performance

Indexes primarily exist to enhance performance. But they do not come without a cost. Indexes must be updated during INSERT, UPDATE and DELETE operation, which may slow down performance

Besides, the usefulness of an Index depends on selectivity of a column/columns.

Generally Indexes are more selective if the column/columns have a large number of unique values.

If an Index contains more than one column, it is called CONCATENATED INDEX .

Concatenated index is often more selective than a single key index.

Column positions play an important role in Concatenated index. While using Concatenated Index, be sure to use LEADING columns

Which is Faster: Indexed Retrieval or Full-table Scan?

Full-table scans can be efficient because they require little disk movement. The disk starts reading at one point and continues reading contiguous data blocks.

Index retrievals are usually more efficient when retrieving few records or when using joints with other tables.

If more than 12%,this percentage defers from table to table and depends on the physical I/O, of the table retrieved a full table scan is better.

Avoiding Calculations on Indexed Columns

The optimizer does not use an index if the indexed column is a part of a function (in the WHERE clause). In general, avoid doing calculations on indexed columns, apply function and concatenating on an indexed columns.

Select * from

Account

Where substr(ac_acct_no,1,1) =1

Instead use -

Select * from

Account

Where ac_acct_no like1%

Note: The SQL functionsMIN and MAX are exceptions to this rule and will utilize all available indexes.

Avoiding NOT on Indexed Columns

In general avoid using NOT when testing indexed columns.

When Oracle encounters a NOT, it will choose not to use index and will perform a full-table scan instead.

Remember,indexes are built on what is in a table, but not what is NOT in a table.

For example the following select statement will never use the index onSTUDENT_NUM column

Select * from

student

Where STUDENT_NUM not like9%

Using UNION in Place of OR

In general, always consider the UNION verb instead of OR verb in the WHERE clauses.

Using OR on an indexed column causes the optimizer to perform a full-table scan rather than an indexed retrieval.

Position of Joins in the WHERE Clause

Table joins should be written first before any condition of WHERE clause. And the conditions which filter out the maximum records should be placed at the end after the joins as the parsing is done from BOTTOM to TOP.

Least Efficient :

SELECT . . . .

FROM EMP E

WHERE SAL > 50000

AND JOB = CLERK

AND 25 < (SELECT COUNT(*)

FROM EMP WHERE MGR = E.EMPNO);

Most Efficient :

SELECT . . . .

FROM EMP E

WHERE 25 < (SELECT COUNT(*)

FROM EMP

WHERE MGR = E.EMPNO )

AND SAL > 50000 AND JOB = CLERK;


Nested Loops Join Sort-Merge Join Hash Join Cluster Join

When can be used:Any join Equi joins only Equi joins onlyEqui joins on complete cluster key of clustered

tables only

Optimizer hint:use_nl Use_merge use_hash None

Resource concerns: CPU Temporary segments Memory Storage Disk I/O

init.ora parameters:None sort_area_size hash_join_enabled None db_file_multi block_ hash_area_size

read_count hash_multiblock_io_count

Features:Works with any join Better than nested Better than nested Reduces I/O for master-

loop when index is loop when index is detail Queries

missing or search missing or search

critiria is not restrictive criteria is not restrictive

Drawbacks:Very inefficient Must perform an extra sort Can require lots Clustered data can take when no suitable Cannot return first of memorymore space to store

index exist rows quickly slows down updates and full scan

Side by Side Comparison of Join Methods

ORACLE parser always processes table names from right to left, so the table name you specify last (driving table) is actually the first table processed.

If you specify more than one table in a FROM clause of a SELECT statement, you must choose the table containing the lowest number of rows as the driving table.

When ORACLE processes multiple tables, it uses an internal sort/merge procedure to join those tables.

First, it scans and sorts the first table (the one specified last in the FROM clause).

Next, it scans the second table (the one prior to the last in the FROM clause) and merges all of the rows retrieved from the second table with those retrieved from the first table.

For example:

Table TABA has 16,384 rows.

Table TABB has 1 row.

SELECT COUNT(*) FROM TABA, TABB 0.96 seconds elapsed

SELECT COUNT(*) FROM TABB, TABA 26.09 seconds elapsed

If three tables are being joined, select the intersection table as the driving table.

The intersection table is the table that has many tables dependent on it.

E.g.. The EMP table represents the intersection between the LOCATION table and the CATEGORY table.

SELECT . . .

FROM LOCATION L, CATEGORY C, EMP E

WHERE E.EMP_NO BETWEEN 1000 AND 2000

AND E.CAT_NO = C.CAT_NO

AND E.LOCN = L.LOCN

is more efficient than this next example:

SELECT . . .

FROM EMP E,

LOCATION L, CATEGORY C

WHERE E.CAT_NO = C.CAT_NO

AND E.LOCN = L.LOCN

AND E.EMP_NO BETWEEN 1000 AND 2000

Problems when Converting Index Column Types

Oracle performs simple column type conversion, or casting, when it compares columns of different type. If a numeric column is compared to an alphabetic column, the character column automatically has its type converted to numeric.

Select *

from Account

Where ACCOUNT_ID = 90426001

In fact, because of conversion this statement will actually be processed as:

Select *

from Account

Where to_number(ACCOUNT_ID) = 90426001

But the following statement:

Select *

From acc_txn

Where acc_txn_ref_no =119990012890

Will be processed as:

Select *

From acc_txn

Where acc_txn_ref_no = to_number(119990012890 )

Use DECODE to Reduce Processing

The DECODE statement provides a way to avoid having to scan the same rows repetitively or to join the same table repetitively.

For example:

SELECT COUNT(*), SUM(SAL)

FROM EMP

WHERE DEPT_NO = 0020

ANDENAME LIKE SMITH%;

SELECTCOUNT(*), SUM(SAL)

FROMEMP

WHERE DEPT_NO = 0030

AND ENAME LIKE SMITH%;

You can achieve the same result much more efficiently with DECODE:

SELECT COUNT(DECODE(DEPT_NO,0020, X, NULL))

D0020_COUNT,

COUNT(DECODE(DEPT_NO,0030,X,NULL))

D0030_COUNT,

SUM(DECODE(DEPT_NO,0020, SAL, NULL))

D0020_SAL,

SUM(DECODE(DEPT_NO, 0030, SAL, NULL))

D0030_SAL

FROM EMP

WHERE ENAME LIKE SMITH%;

Similarly,DECODE can be used inGROUP BY orORDER BY clause effectively.

To improve performance, minimize the number of table lookups in queries, particularly if your statements include sub-query SELECTs or multi-column UPDATEs.

For example:

Least Efficient :

SELECTTAB_NAME

FROMTABLES

WHERE

TAB_NAME =

(SELECT TAB_NAME

FROM TAB_COLUMNS

WHERE VERSION = 604)

AND

DB_VER = (SELECTDB_VER

FROMTAB_COLUMNS

WHERE VERSION = 604)

Most Efficient :

SELECT TAB_NAME

FROMTABLES

WHERE (TAB_NAME,DB_VER)=

(SELECT TAB_NAME, DB_VER

FROM TAB_COLUMNS

WHERE VERSION = 604)

Use EXISTS in Place of DISTINCT

Avoid joins that require the DISTINCT qualifier on the SELECT list when you submit queries used to determine information at the owner end of a one-to-many relationship (e.g. departments that have many employees).

Least Efficient :

SELECTDISTINCT DEPT_NO, DEPT_NAME

FROM DEPT D, EMP E

WHERE D.DEPT_NO = E.DEPT_NO

Most Efficient :

SELECTDEPT_NO, DEPT_NAME

FROMDEPT D

WHEREEXISTS(SELECT X

FROM EMP E

WHERE E.DEPT_NO = D.DEPT_NO);

EXISTS is a faster alternative because the RDBMS kernel realizes that when the sub-query has been satisfied once, the query can be terminated.

Some Dos and Donts

Some SELECT statement WHERE clauses do not use indexes at all. If you have specified an index over a table that is referenced by a clause of type shown in this section Oracle will simply ignore the index.

For each clause that cannot use an index, an alternative approach, which will allow you to get better performance out of your SELECT statements is suggested.

Do Not Use:

Select * from

Account

Where substr(ac_acct_no,1,1) =9

Use:

Select * from

Account

Where ac_acct_no like9%

Do Not Use:

Select *

From fin_trxn

Where ft_trxn_ref_no != 0

Use:

Select *

From fin_trxn

Where ft_trxn_ref_no > 0

Do Not Use:

Select *

From account

Where ac_type || ac_branch =sav001

Use:

Select *

From account

Where ac_type =sav

And ac_branch =sav001

Do Not Use:

Select *

From CLIENT where

to_char(CUTT_OFF_TIME,yyyymmdd) = to_char(sysdate,yyyymmdd)

Use:

Select *

From CLIENT

Where CUT_OFF_DATE >=

trunc(sysdate) and CUT_OFF_TIME < trunc(sysdate) + 1

Do Not Use:

Select *

From acct_trxn

Where to_char(at_value_date,yyyymmdd) > to_char(sysdate,yyyymmdd)

Use:

Select *

From acct_trxn

Where at_value_date >= trunc(sysdate) + 1

Do Not Use:

Select *

From acct_trxn

Where to_char(at_value_date,yyyymmdd) < to_char(sysdate,yyyymmdd)

Use:

Select *

From acct_trxn

Where at_value_date < trunc(sysdate)

Do Not Use:

Select *

From acct_trxn

Where to_char(at_value_date,yyyymmdd) >= to_char(sysdate,yyyymmdd)

Use:

Select *

From acct_trxn

Where at_value_date >= trunc(sysdate)

Do Not Use:

Select *

From acct_trxn

Where to_char(at_value_date,yyyymmdd) SET AUTOTRACE ON EXPLAIN

SQL>SELECT animal_name FROM aquatic_animal

ORDER BY animal_name;

ANIMAL_NAME

------------------------------

Batty

Bopper

Flipper

3 rows selected.

Execution Plan

----------------------------------------------------------

0 SELECT STATEMENT Optimizer=CHOOSE (Cost=3 Card=10

Bytes=170)

0 SORT (ORDER BY) (Cost=3 Card=10 Bytes=170)

2 1 TABLE ACCESS (FULL) OF AQUATIC_ANIMAL (Cost=1 Card=10 Bytes=170)

SQL*Plus does execute the query. If a query generates a lot of I/O and consumes a lot of CPU, you wont want to kick it off just to see the execution plan.

In that case use following :

SQL> SET AUTOTRACE TRACEONLY EXPLAIN

you are through using autotrace, you can turn the feature off by issuing the

SET AUTOTRACE OFFcommand.

Click to edit Master title style

strtegic1Click to edit Master text styles

Second level

Third level

Fourth level

Fifth level

Click to edit Master text stylesSecond level

Third level

Fourth level

Fifth level

Click to edit Master title style

Click to edit Master subtitle style

Click to edit Master text stylesSecond level

Third level

Fourth level

Fifth level

strtegic1Click to edit Master title style

Click to edit Master text styles

Second level

Third level

Fourth level

Fifth level

Click to edit Master text stylesSecond level

Third level

Fourth level

Fifth level

strtegic1Click to edit Master title style

Click to edit Master text styles

Click to edit Master text stylesSecond level

Third level

Fourth level

Fifth level

strtegic1Click to edit Master title style

Click to edit Master text styles

Second level

Third level

Fourth level

Fifth level

Click to edit Master text styles

Second level

Third level

Fourth level

Fifth level

Click to edit Master text stylesSecond level

Third level

Fourth level

Fifth level

strtegic1Click to edit Master title style

Click to edit Master text styles

Click to edit Master text styles

Second level

Third level

Fourth level

Fifth level

Click to edit Master text styles

Click to edit Master text styles

Second level

Third level

Fourth level

Fifth level

Click to edit Master text stylesSecond level

Third level

Fourth level

Fifth level

strtegic1Click to edit Master title style

Click to edit Master text stylesSecond level

Third level

Fourth level

Fifth level

strtegic1

Click to edit Master text stylesSecond level

Third level

Fourth level

Fifth level

strtegic1Click to edit Master title style

Click to edit Master text styles

Second level

Third level

Fourth level

Fifth level

Click to edit Master text styles

Click to edit Master text stylesSecond level

Third level

Fourth level

Fifth level

strtegic1Click to edit Master title style

Click to edit Master text styles

Click to edit Master text stylesSecond level

Third level

Fourth level

Fifth level

strtegic1Click to edit Master title style

Click to edit Master text styles

Second level

Third level

Fourth level

Fifth level

Click to edit Master text stylesSecond level

Third level

Fourth level

Fifth level

strtegic1Click to edit Master title style

Click to edit Master text styles

Second level

Third level

Fourth level

Fifth level

Click to edit Master text stylesSecond level

Third level

Fourth level

Fifth level