Sie sind auf Seite 1von 17

TATA CONSULTANCY SERVICES

Coding and Tuning


Guidelines
for
Developers and Tuners

Confidential
TCS Confidential

TATA CONSULTANCY SERVICES

Overview
Performance is a continuing process as far as database applications are concerned. Performance
comes into picture at various stages of software development lifecycle right from Requirement
Analysis through Design, Development, Testing, Deployment to Maintenance. It is with this aim
we have drafted this document. This document will come into use in the Development and
Deployment stages of all Oracle Database Applications. It aims at

Developing code with performance in mind

Reducing time for Tuning before code rolls out into Production

Confidential
TCS Confidential

TATA CONSULTANCY SERVICES

INDEX
Overview...........................................................................................................................................................2
INDEX.............................................................................................................................................................3
SQL Tuning Guidelines..................................................................................................................................4
Avoid datatype mismatch...........................................................................................................................4
Avoid functions on Indexed columns........................................................................................................4
Define initial columns in composite indexes.............................................................................................4
Using WHERE instead of HAVING.........................................................................................................5
Avoid nested queries...................................................................................................................................6
Using driving table in RULE based Optimizer........................................................................................6
Not exists and Outer joins.....................................................................................................................6
Do not use NOT EQUAL...........................................................................................................................6
Functional index for NVL columns...........................................................................................................6
Reduce the Number of Trips to the Database..........................................................................................7
Using TRUNCATE instead of DELETE..................................................................................................8
Advantages of using DECODE..................................................................................................................8
Counting rows from Table.........................................................................................................................9
Use UNION-ALL in Place of UNION (Where Possible).........................................................................9
Use WHERE Instead of ORDER BY Clause.........................................................................................10
Use IN in Place of OR...............................................................................................................................11
Full Table Scans are better?....................................................................................................................12
When to go for Fast Full Scans................................................................................................................12
Bitmap Indexes..........................................................................................................................................12
Using composite indexes...........................................................................................................................12
PL/SQL Tuning Guidelines..........................................................................................................................13
Use of bind variables................................................................................................................................13
Avoiding unnecessary database calls......................................................................................................13
Use of PLS_INTEGER.............................................................................................................................14
Avoid BINARY_INTEGER.....................................................................................................................14
Pinning stored procedures.......................................................................................................................14
Using WHEN clause in triggers...............................................................................................................14
Use AFTER row triggers..........................................................................................................................14
Use of Bulk binding..................................................................................................................................15
Use of LIMIT clause.................................................................................................................................15
PRO* C Tuning Guidelines..........................................................................................................................16

Confidential
TCS Confidential

TATA CONSULTANCY SERVICES

Precompiler Options.................................................................................................................................16

SQL Tuning Guidelines


Avoid datatype mismatch
Avoid data type mismatch for index columns. If there are datatype mismatches then the index
on that particular column will not be used and a FULL TABLE SCAN will be made.

Avoid functions on Indexed columns


Avoid functions on index columns. In this case too the presence of a function will make the
optimizer go for FULL TABLE SCAN.

Define initial columns in composite indexes

Confidential
TCS Confidential

TATA CONSULTANCY SERVICES

Ensure initial columns are defined when using a composite index. If the initial columns are not
used. Then the composite index will not be made use of.
For eg:
Consider a table in which brand and product columns have a composite index. And we
execute this query.
Select count(*)
From products
Where price < 1000;
The composite index will not be made use of. But the same composite index will be hit for
the query given below.
Select count(*)
From products
Where brand = Arrow;
Hence its important to that initial columns are defined while we are making use of
composite indexes. We can hit the index by doing the following.
Select count(*)
From products
Where brand > 0
and price < 1000;

Using WHERE instead of HAVING


Move conditions from having clause to where clause
For eg:
Consider this query
Select brand, sum(price)
From products
Group by brand
Confidential
TCS Confidential

TATA CONSULTANCY SERVICES

Having brand = Arrow;


The above query can be re-written as the one below. This will ensure the index if present
is made use of.
Select brand, sum(price)
From products
Where brand = Arrow
Group by brand;

Avoid nested queries


Rewrite nested queries using joins, whenever possible

Using driving table in RULE based Optimizer


Ensure smallest table appears last when specifying a join query if you are using RULE based
optimizer.

Not exists and Outer joins


Replace not in by not exists or outer join. This will ensure indexes are hit if present.

Do not use NOT EQUAL


Replace != by union or < and >

Functional index for NVL columns


Make use of functional indexes in case NVL has to be avoided.
For eg:

Confidential
TCS Confidential

TATA CONSULTANCY SERVICES


Create index idx_test on test(nvl(column_1,0));

Reduce the Number of Trips to the Database


Every time a SQL statement is executed, ORACLE needs to perform many internal processing
steps; the statement needs to be parsed, indexes evaluated, variables bound, and data blocks
read. The more you can reduce the number of database accesses, the more overhead you can
save.
For example:
There are 3 distinct ways of retrieving data about employees who have employee numbers 0342
or 0291.
Method 1 (Least Efficient) :
SELECT

EMP_NAME, SALARY, GRADE

FROM

EMP

WHERE

EMP_NO = 0342;

SELECT

EMP_NAME, SALARY, GRADE

FROM

EMP

WHERE

EMP_NO = 0291;

Method 2 (Next Most Efficient) :


DECLARE
CURSOR C1(E_NO NUMBER) IS
SELECT

EMP_NAME, SALARY, GRADE

FROM

EMP

WHERE EMP_NO = E_NO;


BEGIN
OPEN C1(342);
FETCH

C1 INTO , , ;

.
.
OPEN C1(291);
Confidential
TCS Confidential

TATA CONSULTANCY SERVICES


FETCH

C1 INTO , , ;

CLOSE C1;
END;
Method 3 (Most Efficient) :
SELECT

A.EMP_NAME, A.SALARY, A.GRADE,

B.EMP_NAME, B.SALARY, B.GRADE,


FROM
EMP

EMP

A,

WHERE
AND

A.EMP_NO = 0342
B.EMP_NO = 0291;

So make use of Stored Procedures where ever possible.

Using TRUNCATE instead of DELETE


When rows are removed from a table, under normal circumstances, the rollback segments are
used to hold undo information; if you do not commit your transaction, Oracle restores the data to
the state it was in before your transaction started.
With TRUNCATE, no undo information is generated. Once the table is truncated, the data cannot
be recovered back. It is faster and needs fewer resources.
Use TRUNCATE rather than DELETE for wiping the contents of small or large tables when you
need no undo information generated.

Advantages of using DECODE


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

COUNT(*), SUM(SAL)

FROM

EMP

Confidential
TCS Confidential

TATA CONSULTANCY SERVICES

WHERE DEPT_NO = 0020


AND

ENAME LIKE SMITH%;

SELECT

COUNT(*), SUM(SAL)

FROM

EMP

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 in GROUP BY or ORDER BY clause effectively.

Counting rows from Table


Contrary to popular belief, COUNT(*) is faster than COUNT(1). If the rows are being returned via
an index, counting the indexed column is faster still.
For eg:
Select COUNT(EMPNO) from emp;

Use UNION-ALL in Place of UNION (Where Possible)


When the query performs a UNION of the results of two queries, the two result sets are merged
via the UNION-ALL operation, and then the result set is processed by a SORT UNIQUE operation
before the records are returned to the user.
If the query had used a UNION-ALL function in place of UNION, then the SORT UNIQUE
operation would not have been necessary, thus improving the performance of the query.
Confidential
TCS Confidential

TATA CONSULTANCY SERVICES

10

For example:
Least Efficient :
SELECT

ACCT_NUM, BALANCE_AMT

FROM

DEBIT_TRANSACTIONS

WHERE

TRAN_DATE = 31-DEC-95

UNION
SELECT

ACCT_NUM, BALANCE_AMT

FROM

CREDIT_TRANSACTIONS

WHERE

TRAN_DATE = 31-DEC-95

Most Efficient :
SELECT

ACCT_NUM, BALANCE_AMT

FROM

DEBIT_TRANSACTIONS

WHERE

TRAN_DATE = 31-DEC-95

UNION ALL
SELECT

ACCT_NUM, BALANCE_AMT

FROM

CREDIT_TRANSACTIONS

WHERE

TRAN_DATE = 31-DEC-95

Use WHERE Instead of ORDER BY Clause


ORDER BY clauses use an index only if they meet 2 rigid requirements.

All of the columns that make up the ORDER BY clause must be contained within a single
index in the same sequence.

All of the columns that make up the ORDER BY clause must be defined as NOT NULL within
the table definition. Remember, null values are not contained within an index.
WHERE clause indexes and ORDER BY indexes cannot be used in parallel.
For example:
Consider a table DEPT with the following fields:

Confidential
TCS Confidential

TATA CONSULTANCY SERVICES


DEPT_CODE

PK

NOT NULL

DEPT_DESC

NOT NULL

DEPT_TYPE

NULL

NON UNIQUE INDEX (DEPT_TYPE)


Least Efficient : (Here, index will not be used)
SELECT

DEPT_CODE

FROM

DEPT

ORDER BY

DEPT_TYPE

Explain Plan:
SORT ORDER BY
TABLE ACCESS FULL
Most Efficient : (Here, index will be used)
SELECT

DEPT_CODE

FROM

DEPT

WHERE

DEPT_TYPE > 0

Explain Plan:
TABLE ACCESS BY ROWID ON EMP
INDEX RANGE SCAN ON DEPT_IDX

Use IN in Place of OR
The following query can be replaced to improve the performance as shown below:
Least Efficient:
SELECT . . .
FROM

LOCATION

WHERE

LOC_ID = 10

OR

LOC_ID = 20

Confidential
TCS Confidential

11

TATA CONSULTANCY SERVICES


OR

12

LOC_ID = 30

Most Efficient:
SELECT . . .
FROM

LOCATION

WHERE LOC_IN IN (10,20,30)

Full Table Scans are better?


When index scan performs more block visitations than a full table scan, better to use full table
scans

When to go for Fast Full Scans


Fast full table scans are an alternative to full table scans when the index contains all the
columns that are needed for the query. This can be used by using Optimizer Hint INDEX_FFS.

Bitmap Indexes
Consider bitmap indexes when where clause predicate contain low-cardinality columns,
contain logical operations such as OR, AND or NOT on those columns. It is advisable that bitmap
indexes are not used in OLTP applications.

Using composite indexes


Make use of composite indexes. These need to be ordered in the decreasing order of
selectivity.

Indexes on Foreign Key


Create indexes on foreign key columns if the queries always retrieve master-detail
relationship-based rows.

Confidential
TCS Confidential

TATA CONSULTANCY SERVICES

13

PL/SQL Tuning Guidelines

Use of bind variables


Making use of bind variables will reduce frequent parsing.

Avoiding unnecessary database calls


Avoid selects against the database when the same functionality can be
achieved in PL/SQL by just assigning to the variables. System variables like UID, SYSDATE can
be assigned to variables without select statements.
We can make use of assignments instead of making a SQL statement.
For eg:
Declare
From_date date;
Confidential
TCS Confidential

TATA CONSULTANCY SERVICES

14

begin
Select sysdate into from_date from dual;
End;
Can be replaced by
Declare
From_date
begin
From_date:=sysdate
End;

Use of PLS_INTEGER
Make use of PLS_INTEGER instead of NUMBER or INTEGER in loop variables as
PLS_INTEGER makes use of machine arithmetic whereas NUMBER and INTEGER makes use
of functional arithmetic. Hence PLS_INTEGER will be faster.

Avoid BINARY_INTEGER
The use of BINARY_INTEGER datatypes within arithmetic operations performs slower than the
same operation using an INTEGER datatype.

Pinning stored procedures


Anonymous PL/SQL should be moved into a stored object when possible and this object then
pinned in the shared pool using dbms_shared_pool.keep() if the object is frequently referenced.

Using WHEN clause in triggers


Use a WHEN clause on the trigger if at all possible so that the trigger is only fired when
absolutely necessary.

Use AFTER row triggers

Confidential
TCS Confidential

TATA CONSULTANCY SERVICES

15

Use AFTER row triggers instead of BEFORE row triggers if at all possible. After row triggers are
faster.

Use of Bulk binding


Bulk binds improve performance by minimizing the number of context switches between PL/SQL
and SQL engines while they pass an entire collection of elements (varray, nested tables, index-by
table, or host array) as bind variables back and forth. Hence make use of BULK COLLECT and
FORALL.

Use of LIMIT clause


Using LIMIT clause during BULK COLLECT will reduce CPU utilization.
For eg:
set serveroutput on
declare
TYPE tstrings IS TABLE OF string(255) INDEX BY BINARY_INTEGER;
type tnumbers IS TABLE OF FLOAT INDEX BY BINARY_INTEGER;
n tstrings;
cursor c is select object_name from user_objects;
bulk_limit number;
begin
open c;
-- first bulk 10
dbms_output.put_line('-- first bulk 10');
bulk_limit := 10;
fetch c bulk collect into n LIMIT bulk_limit;
for i in n.first..n.last loop
dbms_output.put_line(n(i));
end loop;
-- second bulk 15
dbms_output.put_line('-- second bulk 15');
Confidential
TCS Confidential

TATA CONSULTANCY SERVICES

16

bulk_limit := 15;
fetch c bulk collect into n LIMIT bulk_limit;
for i in n.first..n.last loop
dbms_output.put_line(n(i));
end loop;
close c;
end;
/

PRO* C Tuning Guidelines


Precompiler Options
Use HOLD_CURSOR=YES and RELEASE_CURSOR=NO pre-compiler options while
pre-compiling. Using these options when MODE=ANSI will not make use of these options.
These two parameters can be entered in line in a program with the following syntax:
EXEC ORACLE OPTION (HOLD_CURSOR=NO);
EXEC ORACLE OPTION (RELEASE_CURSOR=YES);

MAXOPENCURSORS (default value 10) signifies the initial size of the program cursor cache.
The size of the cursor cache may grow, depending on the values of HOLD_CURSOR and
RELEASE_CURSOR. Hence increase the MAXOPENCURSORS value in pre-compiling options.

Confidential
TCS Confidential

TATA CONSULTANCY SERVICES

Confidential
TCS Confidential

17

Das könnte Ihnen auch gefallen