SQL Tuning
SQL Tuning
SQL Standards
Using Indexes The Optimizer FROM, WHERE Clauses EXPLAIN SQL Trace Sub-Selects and Joins Tips and Tricks
1
I'M FINISHED!
Developers and DBAs must work together to tune the database and the application
SQL Standards
Why are SQL standards important?
Maintainability, readability
Performance: If SQL is the same as a (recently) executed statement, it can be re-used instead of needing to be reparsed
SQL Standards
Question: which of these statements are the same?
SQL Standards
Answer: None
11
Table: EMP
5 5, 9 empno 4 9 1 3 5 2 7 8 6 fname lisa jackie john larry jim mary harold mark gene lname ... baker miller larson jones clark smith simmons burns harris
1 2
7 8 9
12
Indexes: Caveats
Sometimes a table scan cannot be avoided Not every column should be indexed--there is performance overhead on Inserts, Updates, Deletes Small tables may be faster with a table scan Queries returning a large number (> 5-20%) of the rows in the table may be faster with a table scan
13
15
Indexes: Functions
Question: which of these statements will use the index?
SELECT FROM WHERE ... WHERE * emp TRUNC(hiredate) = TRUNC(SYSDATE); fname || lname = 'MARYSMITH';
SELECT * FROM emp WHERE hiredate BETWEEN TRUNC(SYSDATE) AND TRUNC(SYSDATE)+1 ... WHERE fname = 'MARY' AND lname = 'SMITH';
16
Indexes: Functions
First statement will not use index. Second statement will use index. Using a function, calculation, or other operation on an indexed column disables the use of the Index.
17
Indexes: NOT
Question: which of these statements will use the index?
SELECT FROM WHERE ... ... * dept deptno != 0; deptno NOT = 0; deptno IS NOT NULL;
18
Indexes: NOT
First statement will not use index. Second statement will use index. Using NOT excludes indexed columns.
19
The Optimizer
The WHERE/FROM rules on the following pages apply to the Rule-based optimizer (Oracle). If the Cost-based Optimizer is used, Oracle will attempt to reorder the statements as efficiently as possible (assuming statistics are available). DB2 and Sybase use only a Cost-based optimizer The Optimizer's access paths can be overridden in Oracle and Sybase (not DB2)
20
21
22
EMP shares columns with DEPT and SALGRADE, so use as the driving table
23
24
SELECT * FROM emp E WHERE 25 > (SELECT COUNT(*) FROM emp M WHERE M.mgr = E.empno) AND E.sal > 50000
25
26
WHERE: USING OR
Question: which of these statements will more effective?
SELECT * FROM emp E WHERE 25 > (SELECT COUNT(*) FROM emp M WHERE M.mgr = E.empno) OR E.sal > 50000 SELECT FROM WHERE OR * emp E E.sal > 50000 25 > (SELECT COUNT(*) FROM emp M WHERE M.mgr = E.empno)
27
WHERE: USING OR
Using an "OR" sub query, place it last. It will more cost effective.
28
29
31
33
SELECT E.* FROM emp E, dept D WHERE D.dname = 'SALES' AND D.deptno = E.deptno;
34
JOIN: better than Exists if the number of matching rows in DEPT is large
Explain
Display the access path the database will use (e.g., use of indexes, sorts, joins, table scans) Oracle: Sybase: DB2: EXPLAIN SHOWPLAN EXPLAIN
Oracle Syntax:
EXPLAIN PLAN SET STATEMENT_ID = 'statement id' INTO PLAN_TABLE FOR
statement
Explain
Example 1: IN subquery
SELECT * FROM emp E WHERE E.deptno IN ( SELECT D.deptno FROM dept D WHERE D.dname = 'SALES');
Result:
3 joins MERGE JOIN 1 dynamic view SORT (JOIN) 2 table scans TABLE ACCESS (FULL) OF EMP 3 sorts SORT (JOIN) VIEW SORT (UNIQUE) TABLE ACCESS (FULL) OF DEPT
36
Explain
Example 2: "EXISTS" subquery
SELECT * FROM emp e WHERE EXISTS SELECT FROM WHERE AND
Result:
FILTER TABLE ACCESS (FULL) OF EMP TABLE ACCESS (BY INDEX ROWID) OF DEPT INDEX (UNIQUE SCAN) OF PK_DEPT (UNIQUE)
37
Explain
Example 3: Join (no subquery)
SELECT E.* FROM emp E, dept D WHERE D.dname = 'SALES' AND D.deptno = E.deptno;
Result:
NESTED LOOPS TABLE ACCESS (FULL) OF EMP TABLE ACCESS (BY INDEX ROWID) OF DEPT INDEX (UNIQUE SCAN) OF PK_DEPT (UNIQUE)
38
SQL Trace
Use SQL Trace to determine the actual time and resource costs for for a statement to execute. Step 1: ALTER SESSION SET SQL_TRACE TRUE; Step 2: Execute SQL to be traced:
SELECT E.* FROM emp E, dept D WHERE D.dname = 'SALES' AND D.deptno = E.deptno;
SQL Trace
Step 4: Trace file is created in <USER_DUMP_DEST> directory on the server (specified by the DBA).
Trace file Formatted output file destination for Explain user/passwd for Explain
40
SQL Trace
Step 6: view the output file:
... SELECT E.* FROM emp E, dept D WHERE D.dname = 'SALES' AND D.deptno = E.deptno; call count ------- -----Parse 1 Execute 1 Fetch 2 ------- -----total 4
cpu elapsed disk query current -------- ---------- ---------- ---------- ---------0.00 0.00 0 0 0 0.00 0.00 0 0 0 0.00 0.00 4 19 3 -------- ---------- ---------- ---------- ---------0.00 0.00 4 19 3
Misses in library cache during parse: 0 Optimizer goal: CHOOSE Parsing user id: 62 (PMARKS) Rows ------6 14 14 14 Row Source Operation --------------------------------------------------NESTED LOOPS TABLE ACCESS FULL EMP TABLE ACCESS BY INDEX ROWID DEPT INDEX UNIQUE SCAN (object id 4628)
EXPLAIN output
41
42
SELECT e.deptno, e.lname EXISTS: no sort FROM emp e WHERE EXISTS ( SELECT 'X' FROM dept d WHERE d.deptno = e.deptno);
44
INSERT INTO archive BEFORE: 3 statements VALUES (:vardate, :varid, ...) are used to perform 1 Insert
INSERT INTO emp_archive VALUES (SYSDATE, emp_seq.NEXTVAL, ...) AFTER: only 1 statement is needed
45
SELECT d.dname, e.lname FROM dept d, emp e, dual x WHERE d.deptno AND e.empno AND NVL('X', AND NVL('X',
BEFORE: 2 round-trips
(+) = 10 (+) = 7369 x.dummy) = NVL('X', e.ROWID (+)) x.dummy) = NVL('X', d.ROWID (+));
46
~ 50% faster
47
BEFORE: 2 round-trips
AFTER: only 1
48
49
Using a Sequence INSERT INTO emp VALUES (emp_seq.NEXTVAL, ...); ensures that you always have a unique number, or and does not require any SELECT emp_seq.NEXVAL table reads INTO :new_empno FROM dual;
51
THANK YOU
52
WHERE AND
1,000 rows