Friday, May 8, 2009

Tips for writing efficient SQL Queries


If your query will return more than 20 percent of the rows in the table, use a full-table scan rather than an index scan (Rules 20-80-20)

2

Keep statistics up to date

3

Use the SHARED_CURSOR parameter

4

Use different tablespaces for tables and indexes

5

Use table partitioning (and local indexes) when appropriate (partitioning is an extra cost feature)

6

Use SQL standards and conventions to reduce parsing

7

Avoid joining too many tables

8

Use hints as appropriate

9

Avoid full table scans on large tables

10

Monitor index browning (due to deletions; rebuild as necessary)




  1. Network traffic is reduced. This can have a significant impact on performance if the table has a large number of columns, or the table has a long or long raw column (both of which can be upto 2 GB in length). These types of columns will take a long time to transfer over the network and so they should not be fetched from the database unless they are specifically required.

  1. The code is easier to understand.

  1. It could save the need for changes in the future. If any columns is added to or removed from the base table/view, then “select * “statement can produce wrong results set and statement may fail.

    • Use table alias: Always use table alias and prefix all column names with the aliases when you
    • are using more than one table.

    • Never compare NULL to anything else: All expressions return NULL if one of the operands is NULL. This is applicable for all operators except Concatenation operator (||).

    • Use Bind Variables: It is also better to use bind variables in queries. That way the query becomes generic and therefore re-usable. For example, instead of writing query like –

o SELECT ename, sal FROM emp WHERE deptno = 20;

o Change it to –

o SELECT ename, sal FROM emp WHERE deptno = :deptno;

o The first query can be re-used for deptno number 20 only, whereas the second query can be reused for any other deptno also.

    • SQL Writing Convention: It is a good practice to use a standard syntax for wiring SQL queries. We will recommend following standards to use while writing SQL queries. Write all standard SQL TEXT in upper case:

For example:

SELECT ename, sal FROM emp WHERE deptno = 20;

Write all non standard SQL TEXT (Table name, Column name etc) in lower case:

For example:

SELECT ename, sal FROM emp WHERE deptno = 20;

Note:-

It is important to write similar SQL statement in same case.

For example: Oracle will reparse following queries as they are not written in the same case

Select * from EMP;

Select * from emp;

  • Use EXISTS instead of DISTINCT: Use EXISTS in place of DISTINCT if you want the result set to contain distinct values while joining tables.

For example:

SELECT DISTINCT d.deptno, d.dname FROM dept d, emp e

WHERE d.deptno = e.deptno;

The following SQL statement is a better alternative.

SELECT d.deptno, d.dname FROM dept d WHERE EXISTS

(SELECT e.deptno FROM emp e WHERE d.deptno = e.deptno);

  • Use of expressions and indexes: The optimizer fully evaluates expressions whenever possible and translates certain syntactic constructs into equivalent constructs. This is done either because Oracle can more quickly evaluate the resulting expression than the original

The original expression is merely a syntactic equivalent of the resulting expression. Any computation of constants is performed only once when the statement is optimized rather than each time the statement is executed. Consider these conditions that test for salaries greater than $2000.

sal > 24000/12

sal > 2000

sal*12 > 24000

If a SQL statement contains the first condition, the optimizer simplifies it into the second condition. Please note that optimizer does not simplify expressions across comparison operators. The optimizer does not simplify the third expression into the second. For this reason, we should write conditions that compare columns with constants whenever possible, rather than conditions with expressions involving columns.

The Optimizer does not use index for the following statement:

SELECT * FROM emp WHERE sal*12 > 24000 ;

Instead of this use the following statement:

SELECT * FROM emp WHERE sal > 24000/12 ;

  • Use of NOT operator on indexed columns: Never use NOT operator on an indexed column.Whenever Oracle encounters a NOT on an index column, it will perform full-table scan.

For Example:

SELECT * FROM emp WHERE NOT deptno = 0;

Instead use the following:

SELECT * FROM emp WHERE deptno > 0;

  • Function or Calculation on indexed columns: Never use a function or calculation on an indexed column. If there is any function is used on an index column, optimizer will not use index.

For Example: Do not use until need exactly match string:

SELECT * FROM emp WHERE SUBSTR (ename, 1, 3) = 'MIL';

Use following instead:

SELECT * FROM emp WHERE ename LIKE 'MIL%';

Do not use the following as || is the concatenate function. Like other functions and it disables index.

SELECT * FROM emp WHERE ename || job = 'MILLERCLERK'