Date post: | 07-Apr-2018 |
Category: |
Documents |
Upload: | rajaduraia |
View: | 226 times |
Download: | 0 times |
of 49
8/6/2019 SQL Tuning#1
1/49
SQL Tuning Session ISQL Tuning Session I
8/6/2019 SQL Tuning#1
2/49
OverviewOverview
2
SQL Writing Process
SQL Standards
Using Indexes
The Optimizer
FROM, WHERE Clauses
EXPLAIN
SQL Trace
Sub-Selects and Joins
Tips and Tricks
8/6/2019 SQL Tuning#1
3/49
SQL Writing ProcessSQL Writing Process
3
Step 1: What information do I need? Columns
Step 2: Where is it? Tables
Step 3: Write SQL:
SELECT columns
FROM tables
WHERE ... (joins, filters, subqueries)
8/6/2019 SQL Tuning#1
4/49
SQL Writing ProcessSQL Writing Process
There are many, many ways to get the right results,
but only one is the fastest way1000-to-1
improvements are attainable!
Inefficient SQL can dramatically degrade the
performance of the entire system
Developers and DBAs must work together to tune
the database and the application
8/6/2019 SQL Tuning#1
5/49
PrePre--Tuning QuestionsTuning Questions
5
How long is too long?
Is the statement running on near-production
volumes?
Is the optimal retrieval path being used?
How often will it execute?
When will it execute?
8/6/2019 SQL Tuning#1
6/49
SQL StandardsSQL Standards
6
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
8/6/2019 SQL Tuning#1
7/49
SQL StandardsSQL Standards
7
Question: which of these statements are the same?
A. SELECT LNAME FROM EMP WHERE EMPNO = 12;
B. SELECT lname FROM emp WHERE empno = 12;
C. SELECT lname FROM emp WHERE empno = :id;
D. SELECT lname FROM empWHERE empno = 12;
8/6/2019 SQL Tuning#1
8/49
SQL StandardsSQL Standards
8
Answer: None
Whitespace, case, bind variables vs. constants all
matter
Using standards helps to ensure that equivalent SQL
can be reused.
8/6/2019 SQL Tuning#1
9/49
Tables Used in theTables Used in the ExamplesExamples
9
deptno
dname
loc
DEPT
empno
mgr
jobdeptno
fname
lname
comm
hiredate
grade
sal
EMP
grade
losal
hisal
SALGRADE
8/6/2019 SQL Tuning#1
10/49
SQL Standards: ExampleSQL Standards: Example
10
SELECT E.empno,
D.dname
FROM emp E,
dept D
WHERE E.deptno = D.deptno
AND (D.deptno = :vardeptOR E.empno = :varemp);
Keywords upper case
and left-aligned
Columns on new lines
Use std. table aliases
Separate w/ one space
Use bind variables
AND/OR on new lines
No space before/after
parentheses
8/6/2019 SQL Tuning#1
11/49
Indexes: What are they?Indexes: What are they?
11
An index is a database object used to speed retrievalof rows in a table.
The index contains only the indexed value--usually the
key(s)--and a pointer to the row in the table.
Multiple indexes may be created for a table
Not all indexes contain unique values
Indexes may have multiple columns (e.g., Oracle
allows up to 32)
8/6/2019 SQL Tuning#1
12/49
Indexes and SQLIndexes and SQL
12
If a column appears in a WHERE clause it is a
candidate for being indexed.
If a column is indexed the database can used the
index to find the rows instead of scanning the table.
If the column is not referenced properly, however,
the database may not be able to used the index and
will have to scan the table anyway.
Knowing what columns are and are not indexed can
help you write more efficient SQL
8/6/2019 SQL Tuning#1
13/49
Example: Query without IndexExample: Query without Index
13
No index exists for column EMPNO on table EMP, soa table scan must be performed:
empno fname lname...4 lisa baker
9 jackie miller
1 john larson
3 larry jones
5 jim clark
2 mary smith
7 harold simmons8 mark burns
6 gene harris
Table: EMP
SELECT *FROM emp
WHERE empno = 8
8/6/2019 SQL Tuning#1
14/49
Example: Query with IndexExample: Query with Index
14
7 8 9
empno fname lname ...
4 lisa baker
9 jackie miller
1 john larson
3 larry jones5 jim clark
2 mary smith
7 harold simmons
8 mark burns
6 gene harris
Table: EMP
5
Index: PK_EMP
EMP (EMPNO)
1, 4 5, 9
1 2
3 4
5 6
SELECT *FROM emp
WHERE empno = 8
Column EMPNO is indexed, so it can be used to find
the requested row:
8/6/2019 SQL Tuning#1
15/49
Indexes: CaveatsIndexes: Caveats
15
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
8/6/2019 SQL Tuning#1
16/49
Indexes: FunctionsIndexes: Functions
16
Using a function, calculation, or other operation on anindexed column disables the use of the Index
SELECT *
FROM emp
WHERE TRUNC(hiredate) = TRUNC(SYSDATE);...
WHERE fname || lname = 'MARYSMITH';
SELECT *FROM emp
WHERE hiredate BETWEEN TRUNC(SYSDATE)AND TRUNC(SYSDATE)+1
...WHERE fname = 'MARY'
AND lname = 'SMITH';
Will NOT use index
WILL use index
8/6/2019 SQL Tuning#1
17/49
Indexes: NOTIndexes: NOT
17
Using NOT excludes indexed columns:
SELECT *
FROM deptWHERE deptno != 0;
... deptnoNOT = 0;
... deptno IS NOT NULL;
SELECT *
FROM deptWHERE deptno >0;
Will NOT use index
WILL use index
8/6/2019 SQL Tuning#1
18/49
The OptimizerThe Optimizer
18
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).
8/6/2019 SQL Tuning#1
19/49
FROM Clause: Driving TableFROM Clause: Driving Table
19
Specify the driving table last in the FROM Clause:
SELECT *
FROM dept D, -- 10 rows
emp E -- 1,000 rowsWHERE E.deptno = D.deptno;
SELECT *FROM emp E, -- 1,000 rows
dept D -- 10 rows
WHERE E.deptno = D.deptno;
Driving table is EMP
Driving table is DEPT
8/6/2019 SQL Tuning#1
20/49
FROM Clause: Intersection TableFROM Clause: Intersection Table
20
When joining 3 or more tables, use the Intersection table(with the most shared columns) as the driving table:
SELECT *
FROM dept D,salgrade S,
emp EWHERE E.deptno = D.deptno
AND E.grade = S.grade;
EMP shares columns with
DEPT and SALGRADE,
so use as the driving table
8/6/2019 SQL Tuning#1
21/49
WHERE: Discard EarlyWHERE: Discard Early
21
Use WHERE clauses first which discard the maximum
number of rows:
SELECT *
FROM emp EWHERE E.empno IN (101, 102, 103)
AND E.deptno > 10;
3 rows
90,000 rows
8/6/2019 SQL Tuning#1
22/49
WHERE: AND Subquery FirstWHERE: AND Subquery First
22
When using an "AND" subquery, place it first:
SELECT *
FROM emp EWHERE E.sal > 50000
AND 25 > (SELECT COUNT(*)
FROM emp M WHERE M.mgr = E.empno)
SELECT *
FROM emp EWHERE 25 > (SELECT COUNT(*)
FROM emp M
WHERE M.mgr = E.empno)
AND E.sal > 50000
CPU = 156 sec
CPU = 10 sec
8/6/2019 SQL Tuning#1
23/49
WHERE: OR Subquery LastWHERE: OR Subquery Last
23
When using an "OR" subquery, place it last:
SELECT *
FROM emp EWHERE 25 > (SELECT COUNT(*)
FROM emp M
WHERE M.mgr = E.empno)
OR E.sal > 50000
SELECT *FROM emp E
WHERE E.sal > 50000OR 25 > (SELECT COUNT(*)
FROM emp M
WHERE M.mgr = E.empno)
CPU = 100 sec
CPU = 30 sec
8/6/2019 SQL Tuning#1
24/49
WHERE: Filter First, Join LastWHERE: Filter First, Join Last
24
When Joining andFiltering, specify the Filter condition
first, Joins last.
SELECT *
FROM emp E,dept D
WHERE (E.empno = 123OR D.deptno > 10)
AND E.deptno = D.deptno;
Filter criteria
Join criteria
8/6/2019 SQL Tuning#1
25/49
Subqueries: IN vs. EXISTSSubqueries: IN vs. EXISTS
25
Use EXISTS instead of IN in subqueries:
SELECT E.*
FROM emp E
WHERE E.deptno IN (
SELECT D.deptnoFROM dept DWHERE D.dname = 'SALES');
SELECT *
FROM emp E
WHERE EXISTS (SELECT 'X'FROM dept D
WHERE D.deptno = E.deptnoAND D.dname = 'SALES');
IN: Both tables are
scanned
EXISTS: Only outer table
is scanned; subquery
uses index
8/6/2019 SQL Tuning#1
26/49
Subquery vs. JoinSubquery vs. Join
26
Use Join instead of Subquery :
SELECT *
FROM emp E
WHERE E.deptno IN (SELECT D.deptnoFROM dept D
WHERE D.dname = 'SALES');
SELECT E.*
FROM emp E,dept D
WHERE D.dname = 'SALES'
AND D.deptno = E.deptno;
IN: Both tables are
scanned
JOIN: Only one table is
scanned, other uses index
8/6/2019 SQL Tuning#1
27/49
Join vs. EXISTSJoin vs. EXISTS
27
Best performance depends on subquery/driving table:
SELECT *
FROM emp E
WHERE EXISTS (
SELECT 'X'FROM dept DWHERE D.deptno = E.deptno
AND D.dname = 'SALES');
SELECT E.*
FROM emp E,dept D
WHERE D.dname = 'SALES'
AND D.deptno = E.deptno;
EXISTS: better than Join if
the number of matching
rows in DEPT is small
JOIN: better than Exists if
the number of matchingrows in DEPT is large
8/6/2019 SQL Tuning#1
28/49
ExplainExplain
28
Display the access path the database will use (e.g., useof indexes, sorts, joins, table scans)
Oracle: EXPLAIN
Sybase: SHOWPLAN
DB2: EXPLAIN
Oracle Syntax:
EXPLAIN PLANSET STATEMENT_ID = 'statement id'
INTO PLAN_TABLE FORstatement
Requires Select/Insert privileges on PLAN_TABLE
8/6/2019 SQL Tuning#1
29/49
ExplainExplain
29
Example 1: IN subquerySELECT *FROM emp E
WHERE E.deptno IN (SELECT D.deptno
FROM dept DWHERE D.dname = 'SALES');
Result:MERGE JOINSORT(JOIN)
TABLE ACCESS (FULL) OF EMPSORT (JOIN)
VIEWSORT(UNIQUE)
TABLE ACCESS (FULL) OF DEPT
3 joins
1 dynamic view
2 table scans
3 sorts
8/6/2019 SQL Tuning#1
30/49
ExplainExplain
30
Example 2: "EXISTS" subquerySELECT *FROM emp e
WHERE EXISTS (SELECT 'x'
FROM dept dWHERE d.deptno = e.deptno
AND d.dname = 'SALES');
Result:
FILTER
TABLE ACCESS (FULL) OF EMPTABLE ACCESS (BY INDEX ROWID) OF DEPT
INDEX (UNIQUE SCAN) OF PK_DEPT (UNIQUE)
1 table scan
1 index scan1 index access
8/6/2019 SQL Tuning#1
31/49
ExplainExplain
31
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 EMPTABLE ACCESS (BY INDEX ROWID) OF DEPT
INDEX (UNIQUE SCAN) OF PK_DEPT (UNIQUE)
1 table scan
1 index scan
1 index access
8/6/2019 SQL Tuning#1
32/49
SQL TraceSQL Trace
32
Use SQL Trace to determine the actualtime andresource 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 DWHERE D.dname = 'SALES'
AND D.deptno = E.deptno;
Step 3: ALTER SESSION SET SQL_TRACE FALSE;
8/6/2019 SQL Tuning#1
33/49
SQL TraceSQL Trace
33
Step 4: Trace file is created in
directory on the server (specified by the DBA).
Step 5: Run TKPROF (UNIX) to create a formatted
output file:
tkprofechd_ora_15319.trc$HOME/prof.out
table=plan_tableexplain=dbuser/passwd
Trace file
Formatted output file
destination for Explainuser/passwd for Explain
8/6/2019 SQL Tuning#1
34/49
SQL TraceSQL Trace
34
Step 6: view the output file:...SELECT E.*FROM emp E, dept D
WHERE D.dname = 'SALES' AND D.deptno = E.deptno;
call count cpu elapsed disk query current rows------- ------ -------- ---------- ---------- ---------- ---------- ----------Parse 1 0.00 0.00 0 0 0 0Execute 1 0.00 0.00 0 0 0 0Fetch 2 0.00 0.00 4 19 3 6------- ------ -------- ---------- ---------- ---------- ---------- ----------total 4 0.00 0.00 4 19 3 6
Misses in library cache during parse: 0Optimizer goal: CHOOSEParsing user id: 62 (PMARKS)
Rows Row Source Operation------- ---------------------------------------------------
6 NESTED LOOPS14 TABLE ACCESS FULL EMP14 TABLE ACCESS BY INDEX ROWID DEPT14 INDEX UNIQUE SCAN (object id 4628)
TIMED_STATISTICS
must be turned on to get
these values
EXPLAIN output
8/6/2019 SQL Tuning#1
35/49
Tips and Tricks: UNION ALLTips and Tricks: UNION ALL
35
Use UNION ALL instead of UNION if there are no
duplicate rows (or if you don't mind duplicates):
SELECT * FROM emp
UNIONSELECT * FROM emp_arch;
SELECT * FROM emp
UNION ALLSELECT * FROM emp_arch;
UNION: requires sort
UNION ALL: no sort
8/6/2019 SQL Tuning#1
36/49
Tips and Tricks: HAVING vs. WHERETips and Tricks: HAVING vs. WHERE
36
With GROUP BY, use WHERE instead of HAVING (if the
filter criteria does not apply to a group function):
SELECT deptno,
AVG(sal)FROM emp
GROUP BY deptno
HAVING deptno IN (10, 20);
SELECT deptno,
AVG(sal)FROM emp
WHERE deptno IN (10, 20)GROUP BY deptno;
HAVING: rows arefiltered afterresult
set is returned
WHERE: rows are
filtered first--possibly
far fewer to process
8/6/2019 SQL Tuning#1
37/49
Tips and Tricks: EXISTS vs DISTINCTTips and Tricks: EXISTS vs DISTINCT
37
Use EXISTS instead of DISTINCT to avoid implicit sort (ifthe column is indexed):
SELECT DISTINCTe.deptno,
e.lnameFROM dept d,
emp eWHERE d.deptno = e.deptno;
SELECT e.deptno, e.lname
FROM emp eWHERE EXISTS (
SELECT 'X'FROM dept d
WHERE d.deptno = e.deptno);
DISTINCT: implicit sort
is performed to filter
duplicate rows
EXISTS: no sort
8/6/2019 SQL Tuning#1
38/49
Tips and Tricks: Consolidate SQLTips and Tricks: Consolidate SQL
38
Select from Sequences and use SYSDATE in the
statement in which they are used:
SELECT SYSDATE INTO :vardate FROM dual;
SELECT arch_seq.NEXTVAL INTO :varid FROM dual;
INSERT INTO archiveVALUES (:vardate, :varid, ...)
INSERT INTO emp_archive
VALUES (SYSDATE, emp_seq.NEXTVAL, ...)
BEFORE: 3 statements
are used to perform 1
Insert
AFTER: only 1
statement is needed
8/6/2019 SQL Tuning#1
39/49
Tips and Tricks: Consolidate SQLTips and Tricks: Consolidate SQL
39
Consolidate unrelated statements using outer-joins to thethe DUAL (dummy) table:
SELECT dname FROM dept WHERE deptno = 10;
SELECT lname FROM emp WHERE empno = 7369;
SELECT d.dname,e.lname
FROM dept d,emp e,
dual x
WHERE d.deptno (+) = 10AND e.empno (+) = 7369
A ND NVL('X', x.dummy) = NVL('X', e.ROWID (+))A ND NVL('X', x.dummy) = NVL('X', d.ROWID (+));
BEFORE: 2 round-trips
AFTER: only 1 round-trip
8/6/2019 SQL Tuning#1
40/49
Tips and Tricks: COUNTTips and Tricks: COUNT
40
Use COUNT(*) instead of COUNT(column):
SELECT COUNT(empno)
FROM emp;
SELECT COUNT(*)
FROM emp; ~50% faster
8/6/2019 SQL Tuning#1
41/49
Tips and Tricks: SelfTips and Tricks: Self--JoinJoin
41
Use a self-join (joining a table to itself) instead of twoqueries on the same table:
SELECT mgr INTO :varmgr FROM emp WHERE deptno = 10;
LOOP...
SELECT mgr, lname FROM emp WHERE mgr = :varmgr;
SELECT E.mgr,
E.lnameFROM emp E,
emp M
WHERE M.deptno = 10A ND E.empno = M.mgr;
BEFORE: 2 round-trips
AFTER: only 1
8/6/2019 SQL Tuning#1
42/49
Tips and Tricks: ROWNUMTips and Tricks: ROWNUM
42
Use the ROWNUM pseudo-column to return only the first
Nrows of a result set. (For example, if you just want a
sampling of data):
SELECT *FROM empWHERE ROWNUM
8/6/2019 SQL Tuning#1
43/49
Tips and Tricks: ROWIDTips and Tricks: ROWID
43
The ROWID pseudo-column uniquely identifies a row,
and is the fastest way to access a row:
CURSOR retired_emp_cur ISSELECT ROWIDFROM empWHERE retired = 'Y';
...FOR retired_emp_rec IN retired_emp_cur LOOP
SELECT fname || ' ' || lname
INTO :printable_nameFROM empWHERE ROWID = retired_emp_rec.ROWID;
...
Instead of selecting the
key column(s), ROWID is
used to identify the row
for later use
8/6/2019 SQL Tuning#1
44/49
Tips and Tricks: SequencesTips and Tricks: Sequences
44
Use a Sequence to generate unique values for a table:
SELECT MAX(empno)
INTO :new_empnoFROM emp;
...INSERT INTO emp
VALUES (:new_empno + 1, ...);
INSERT INTO emp
VALUES (emp_seq.NEXTVAL, ...);orSELECT emp_seq.NEXVALINTO :new_empno FROM dual;
Using a Sequence
ensures that you always
have a unique number,and does not require any
table reads
MAX(empno) requires a
sort and an index scan
INSERT could fail with a
Duplicate error if someoneelse gets there first
8/6/2019 SQL Tuning#1
45/49
Tips and Tricks: Connect ByTips and Tricks: Connect By
45
Use CONNECT BY to construct hierarchical queries:
SELECT LPAD(' ',4*(LEVEL-1)) || lname Name,
JobFROM emp
WHERE job != 'CLERK'
START WITH job = 'PRESIDENT'CONNECT BY PRIOR empno = mgr;
Name Job
King PRESIDENT
Jones MANAGER
Scott ANALYST
Ford ANALYST
Blake MANAGER
Allen SALESMAN
Ward SALESMAN
Martin SALESMANTurner SALESMAN
Clark MANAGER
8/6/2019 SQL Tuning#1
46/49
Tips and Tricks: Cartesian ProductsTips and Tricks: Cartesian Products
46
Avoid Cartesian products by ensuring that the tables arejoined on all shared keys:
SELECT *
FROM dept, -- 10 rows
salgrade, -- 20 rows
emp; -- 1,000 rows
SELECT *
FROM dept, -- 10 rows
salgrade, -- 20 rows
emp -- 1,000 rows
WHERE E.deptno = D.deptno
AND E.grade = S.grade;
10 * 1000 * 20 = 200,000 rows
1,000 rows
8/6/2019 SQL Tuning#1
47/49
8/6/2019 SQL Tuning#1
48/49
Structure Of IndexesStructure Of Indexes
B*-tree indexes(Default)
Reverse key indexes
Bitmap indexes
Function-based indexes
Invisib
le Indexes(11g)
8/6/2019 SQL Tuning#1
49/49
DISTINCT vs. GROUP BYDISTINCT vs. GROUP BY
What is the performance
comparison between the above if
the aggregate function not used in
SELECT?
Both will give the same result and
will not have much difference in
performance and can be
interch
anged.