sql tuning#1

Upload: rajaduraia

Post on 07-Apr-2018

241 views

Category:

Documents


0 download

TRANSCRIPT

  • 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.