Oracle SQL Perfomance

  • Upload
    sefdeni

  • View
    231

  • Download
    0

Embed Size (px)

Citation preview

  • 8/13/2019 Oracle SQL Perfomance

    1/13

    White Paper:

    Using Query Hints for Top SQL Performance

    Author: Randy Cunningham

  • 8/13/2019 Oracle SQL Perfomance

    2/13

    Introduction

    Ask a diverse sample of Oracle professionals for their opinion concerning query hints, and their responses will tend to

    fall into one of three groupings:

    1) What are hints all about, anyway?

    2) Hints are one of the coolest features in Oracle, and they have rescued my career.

    3) Hints are evil, and cause far more problems than they solve. Never, never use hints!

    In reality, hints can be detrimental to the performance and scalability of a database. Also, hints can be useful for

    achieving an optimally performing database. The key to success is understanding when, where, why and how hints

    should be used.

    What is a hint?

    A hint is a special syntax of a comment in a SQL statement block that specifies an instruction, or hint, to Oracles

    cost-based optimizer (CBO). The optimizer uses hints to influence or constrain its choice of an execution plan. Hints

    may appear in SQL originating from SQL*Plus, PL/SQL, Java, Toad, ODBC, C++, Cobol or any application with an

    Oracle SQL interface.

    Hints are specified within a statement block using either style of comment that Oracle supports:

    {DELETE|INSERT|SELECT|UPDATE} /*+ hint [text] [hint[text]]... */

    or

    {DELETE|INSERT|SELECT|UPDATE} --+ hint [text] [hint[text]]...

    where:

    DELETE, INSERT, SELECT, or UPDATE is a query keyword that begins a statement block. Comments containing hints

    must appear immediately following these keywords.

    + is a plus sign that causes Oracle to interpret the comment as a list of hints. The plus sign must follow immediatelyafter the comment delimiter (no space is permitted).

    hint is a validly constructed hint. The space between the plus sign and the hint is optional, and is recommended in

    PL/SQL prior to Oracle9i. If the comment contains multiple hints, then separate the hints by at least one space.

    text is other commenting text that can be interspersed with the hints.

    What do hints do?

    Hints enable you to influence goals, behaviors, methods and choices for which the optimizer ordinarily exercises

    defaults. Default optimizer behavior is determined by information such as statistics on the objects in the query,

    system statistics, session parameters and database parameters. Over 100 hints are categorized according to how

    they influence the CBO.

    Optimization goals and approaches

    Ordinarily the optimizer will choose a query plan designed to provide the best overall throughput and efficiency.

    However, quickest response might be a more important goal than overall throughput for an application such as a

    scrollable browser. You can bias the optimizer to do this with a more index-intensive plan by specifying the

    FIRST_ROWS hint. For example:

    SELECT /*+FIRST_ROWS*/ item_class, item_no, uom, description, qty

    FROM item_table JOIN item_availability

  • 8/13/2019 Oracle SQL Perfomance

    3/13

    USING (item_no)

    WHERE item_class = :INPUT_CLASS

    AND qty > 0;

    The hints that influence optimization goals and approaches are: ALL_ROWS, FIRST_ROWS(n), CHOOSE and RULE.

    Access Methods

    You can recommend the use of a specific index, an index processing method, or even a full table scan, as a method

    for accessing a particular table that you specify. Influencing access methods is quite possibly the most prevalent use

    of hints, and it is replete with pitfalls. Note the use of an indexing hint in the subquery:

    SELECT domain_name, domain_owner

    FROM spammers m

    WHERE effdt = (SELECT /*+INDEX_DESC(s uce_effdt) */ MAX(effdt) -- retrieve only the latest

    FROM spammers s WHERE s.domain_name = m.domain_name);

    Here are the hints that influence a choice of access path:

    AND_EQUAL (table_alias index1 index2 ) INDEX (table_alias [index_name])

    CLUSTER (table_alias) INDEX_ASC (table_alias [index_name])

    FULL (table_alias) INDEX_COMBINE (table_alias index1 index2 )

    HASH (table_alias) INDEX_DESC (table_alias [index_name])

    NO_INDEX (table_alias [index_1 index2 ]) INDEX_FFS (table_alias [index_name])

    ROWID (table_alias) INDEX_JOIN (table_alias [index_name])

    INDEX_SS (table_alias

    [index_name])

    Join Order

    The join order of tables in a FROM clause are affected with three hints, LEADING (table_alias), ORDERED and STAR.

    The STAR join method is useful only with a join of 3 or more tables, where the largest table has a concatenated

    index of at least 3 columns and there are no conflicting access or join method hints. The largest table is joined lastin the join order, using a nested loops join to its qualifying concatenated index.

    The ORDERED hint will instruct the optimizer to join the tables in the order that they are specified, left to right, in

    the FROM clause. To be beneficial, use of this hint presumes that the query author has arranged the tables in the

    FROM clause according to immutable size and/or selectivity criteria, and that she understands some idiosyncrasy of

    the data distribution that the optimizer does not. This example query is constructed with the ORDERED hint:

    SELECT /*+ ORDERED */ e.last_name, e.first_name, b.branch_name

    FROM employee e JOIN branch b

    ON (branch_id)

    WHERE e.position = BRANCH MANAGER;

    The LEADING hint specifies which table is first in the join order, leaving the remainder of the ordering up to the CBO.

    Join Operations

    The choice of a join method is highly leveraged and can change the elapsed runtime of a query by a factor of up to

    several thousand times, favorably or unfavorably. Following is a synopsis of the hints that influence join operations.

    USE_HASH (table_1 [table_2 ]) HASH_AJ HASH_SJ

    USE_MERGE (table_1 [table_2 ]) MERGE_AJ MERGE_SJ

  • 8/13/2019 Oracle SQL Perfomance

    4/13

    USE_NL (table_1 [table_2 ]) NL_AJ NL_SJ

    DRIVING_SITE (table_alias)

    The anti-join hints HASH_AJ, MERGE_AJ and NL_AJ apply only to NOT IN or NOT EXISTS subquery blocks. The

    semi-join hints HASH_SJ, MERGE_SJ and NL_SJ are meaningful only when specified within EXISTS subquery blocks.

    Examples:

    SELECT /*+ DRIVING_SITE(wh1) */ wh1.*

    FROM my_list ml, big_warehouse_table@dwh wh1, lookup_table@dwh wh2

    WHERE ml.market = wh1.market

    AND wh1.type = wh2.type

    AND wh2.status = ACTIVE;

    SELECT /*+ USE_HASH(E D) d.deptid, e.emplid */

    FROM empl e JOIN dept d

    USING (e.empl_dept = d.deptid)

    WHERE d.dept_location = DENVER;

    SELECT division_name FROM divisionWHERE exists (SELECT /*+HASH_SJ*/ NULL

    FROM employee

    WHERE employee.division_id = division.division_id

    AND bonus > 25000);

    Query Transformations

    The query transformation category of hints has the effect of recasting the query as if it were written entirely

    differently for the same result. For example, observe the employment of a USE_CONCAT hint in this query:

    SELECT /*+ USE_CONCAT */ * FROM pub78

    WHERE (state = 'CO' OR state = 'WY')

    AND UPPER(name) LIKE '%CATHOLIC%'

    The USE_CONCAT hint transforms the query (as confirmed with an EXPLAIN PLAN) as if it had been written:

    SELECT * FROM pub78

    WHERE state = CO

    AND UPPER(name) LIKE '%CATHOLIC%'

    UNION ALL

    SELECT * FROM pub78

    WHERE state = WY

    AND UPPER(name) LIKE '%CATHOLIC%'

    This is a list of the query transformation hints available:

    EXPAND_GSET_TO_UNION NO_EXPAND

    FACT (table_alias) NO_FACT (table_alias)

    MERGE (view_alias) NO_MERGE (view_alias)

    REWRITE [(view1 [view2 ])] NOREWRITE

    STAR_TRANSFORMATION USE_CONCAT

    Parallel Execution

    Characteristics of query parallelism can be altered using parallel execution hints:

  • 8/13/2019 Oracle SQL Perfomance

    5/13

  • 8/13/2019 Oracle SQL Perfomance

    6/13

    A Few Preliminaries

    Ensure that the database environment is using the cost-based optimizer (CBO). This is set with the database

    initialization parameter, OPTIMIZER_MODE, which ordinarily should be set to ALL_ROWS or to CHOOSE. Also, be

    sure that the COMPATIBLE and OPTIMIZER_FEATURES_ENABLE parameters are set to versions that support the hints

    you use.Confirm that the participating tables and their indexes in the query have statistics, and that the statistics are

    reasonably current. Be sure to confirm this for tables within views and subqueries.

    Check that necessary initialization parameters are set. For example, for the PARALLEL hint to work at all, you must

    have Oracle Enterprise Edition, and parallel query servers must be configured using Oracle database initialization

    parameters.

    A Gallery of Ignored Hints

    Incorrect: SELECT * FROM /*+ INDEX(inv,inv_pk) */ inv WHERE item_code like R%;

    Correct: SELECT /*+ INDEX(inv,inv_pk) */ * FROM inv WHERE item_code like R%;

    Explanation: It is essential that the hint immediately follow the keyword; it cannot be elsewhere in the query.

    Incorrect: SELECT /*+ index(team)*/ /*+ full(player)*/ * FROM player JOIN team USING (team_id);Correct: SELECT /*+ index(team) full(player)*/ * FROM player JOIN team USING (team_id);

    Explanation: Place all of the hints for a query block into a single comment.

    Incorrect: SELECT /*+ INDEX_FFS(books books_isbn) */ from books b where b.isbn = :ISBN;

    Correct: SELECT /*+ INDEX_FFS(b books_isbn) */ from books b where b.isbn = :ISBN;

    Explanation: A common error. The table alias, whenever present, must be specified in all hints referencing a table.

    Incorrect: SELECT /* ORDER */ candidate_name FROM candidates JOIN jobs USING (job_code)

    Correct: SELECT /*+ ORDERED */ candidate_name FROM candidates JOIN jobs USING (job_code)

    Explanation: Spelling the hint properly is a requirement, as is the plus sign as the first character of the comment.

    Incorrect: SELECT /*+ PUSH_JOIN_PREDICATE(v) */ name, class_code, instructor

    FROM student_view v LEFT OUTER JOIN classes c USING (class_code) WHERE

    class_code = C;

    Correct: SELECT /*+ PUSH_PRED(v) */ name, class_code, instructor

    FROM student_view v LEFT OUTER JOIN classes c USING (class_code) WHEREclass_code = C;

    Explanation: Hints are not guaranteed to remain stable from one Oracle release to another. Beware!

    Incorrect: SELECT /*+ FIRST_ROWS */ zip_code from student_directory group by zip_code;

    Explanation: This hint is never applied to queries that perform grouping operations.

    Incorrect: SELECT /*+ HASH_AJ */ ssn FROM employee_table WHERE hire_code=15;

    Explanation: This is a valid hint used in an improper context. The HASH_AJ hint applies only to subquery blocks.

    Incorrect: SELECT /*+ INDEX_DESC(TM TEAM_PK) PARALLEL(PLAYER 4) */ player_name, coach, date_joined

    FROM player_view p JOIN team t USING (team_id)

    WHERE t.effdt = (SELECT MAX(effdt) FROM team TM where tm.team_id =

    t.team_id);

    Correct: SELECT /*+ PARALLEL(P.PLAYER 4) */ player_name, coach, date_joined

    FROM player_view p JOIN team t USING (team_id)WHERE t.effdt =

    (SELECT /*+INDEX_DESC(TM TEAM_PK)*/ MAX(effdt)

    FROM team TM where tm.team_id = t.team_id);

    Explanation: Hints generally apply only within the scope of the query block where they appear. Hints for a subquery

    must be included in the subquery itself. Hints to be applied to table(s) in a named or in-line view can be supplied in

    the view query; however, it is better practice to provide a global hint in the top-level query block, as shown above.

  • 8/13/2019 Oracle SQL Perfomance

    7/13

    Scope of Hints: Hinting Views

    For queries involving views, possibly including views nested several levels deep, it can be worthwhile to apply a hint

    within the views. Generally, hints only affect the query block in which they appear. There are two ways to hint

    outside the current query block: (a) global hints or (b) hints imbedded in the affected view. However, imbedded

    hints are not recommended.

    Global Hints

    The execution plan of a view can be hinted from a particular query that references it, directly or indirectly, by using

    the global hint syntax. First, consider the following two related view definitions:

    CREATE VIEW manager AS SELECT * FROM employee e WHERE emp_role in (M,S,F);

    CREATE VIEW officer AS SELECT * FROM manager m WHERE is_officer = Y;

    Now, here is an example of how a global hint might be applied for use of a bitmap index on the EMPLOYEE table:

    SELECT /*+ INDEX(officer.m.e ix_emp_codes) */ dept_name, last_name, first_name

    FROM officer JOIN deptUSING (dept_id);

    Note that the actual view name, OFFICER, was supplied in the hint because it has no alias in the query, while aliases

    were specified as they must be for the view MANAGER and the table EMPLOYEE.

    Global hints come in handy when you are working to optimize a query that references views delivered with an ERP or

    other application system. Global hints enable you to evaluate several plan scenarios without altering the third-party

    view at all.

    Hints Imbedded in Views

    It is possible to imbed a hint within a view. Occasionally, a well-meaning, novice query author will tune a view by

    trying any number of hints in the view and then seeking minimum elapsed time with a query such as this:SELECT * FROM my_view;

    While that might result in improved performance of the view in isolation, typically the inclusion of such a tuned

    view in a real-world query will result in a drastic deterioration of the performance of the query. Alternatively, a

    hinted view might actually benefit one query in which it is used, but could result in worsened performance for other

    queries that use the view.

    The reason for this is because the cost-based optimizer attempts to merge views and subqueries into higher-level

    query block(s) prior to performing optimization. The existence of certain hints in a view suppresses view merging,

    often resulting in uncoordinated, suboptimal query execution plans. (The NOMERGE hint specifically suppresses view

    merging.)

    Incorporating a hint into a named view tends to obscure and scatter relevant performance information, making thetask of query optimization daunting, especially when several hinted views are joined. Oracle Corporation explicitly

    discourages the practice of incorporating hints into view definitions [3] and provides additional detail on the subject

    of view merging.

    If you still believe that you need to hint a view, first understand how the view is being merged into the overall query,

    using EXPLAIN PLAN, then supply your hints to the top-level affected or problem query using global hints, instead of

    imbedding your hints in a view definition.

  • 8/13/2019 Oracle SQL Perfomance

    8/13

    Hint Selection Strategies

    Typically, there are one of two motivations that a query author will have for placing a hint within a query.

    One motivation is recognition that the cost-based optimizer must use some generalized assumptions concerning

    what is most important when it is building a query plan; however, a usual assumption does not apply to the current

    application: Normal behavior for an INSERT is to seek and utilize free space within existing blocks of the table.

    However, if populating a table with many rows as quickly as possible is a more important goal than efficient

    use of space, then INSERT /*+APPEND*/ is a worthy hint. Space reutilization is irrelevant if the table is

    truncated immediately prior to the INSERT, or if there are no DELETE or UPDATE operations performed on

    the table at any time. If there is UPDATE or DELETE activity on the table, using the APPEND hint will

    continue to result in rapid loading; however, subsequent query performance will become slower and slower

    over time as more blocks are added to the table, while empty or nearly empty blocks remain.

    Normal behavior for a SELECT is to devise an execution plan that can be completed in the least amount oftime. However, if the application is a scrollable browser, for example, producing the first rows of the query

    in a few seconds might be a more important goal than the complete query elapsed time, especially if the

    entirety of the result set is infrequently accessed. In this case, SELECT /*+ FIRST_ROWS */ is a worthy

    hint

    Normal behavior for a distributed query is to perform optimization on the local database. The remote tablesare recast as single-table queries with WHERE clauses that might result in an indexed or other optimalaccess path; however, the join operation(s) occur on the local database. The cost-based optimizer presently

    does not have any statistics about network latency or bandwidth, so the query might result in massive

    amounts of data being brought across the network to be joined on the local database, resulting in very slow

    execution. Joining at the remote site can mitigate data volumes in these cases; this can be achieved using

    SELECT /*+ DRIVING_SITE(remote) */.

    Another common motivation for using hints is recognition that there is something evidently wrong with a particular

    query execution plan, because it runs much more slowly than expected. In this case, it is not nearly so clear which

    of more than 100 hints available is going to be effective. So, how do you choose a hint?

    Brute force or guesswork

    Simply throwing a quantity of hints at a problem query is a method that requires the minimal training and

    knowledge. There are even third-party Oracle tuning products that will automate this dubious methodology for

    you. Some advantages of this approach are that it can be delegated to a very junior technician and it keeps us

    looking busy. We can provide management with copious, documented test cases evidencing that we tried

    everything to tune the query, even if we were unsuccessful. Sometimes, this approach even results in a hinted

    query that runs faster. However, random, try this methods rarely reveal the root cause of a performance problem

    and are not a professional means to optimize performance.

    Look at the Execution Plan

    Any time a problem query is isolated, an EXPLAIN PLAN should be run on the query. While EXPLAIN PLAN output on

    long or complex queries can be inscrutable even to experienced Oracle professionals, there very well might be an

    epiphany in the plan that will allow you to create and test a hypothesis.

    For example, you notice that a subquery on the ZIPCODE_LOOKUP table is a full table scan. That doesnt seem

    optimal, and you want to test the hypothesis that the subquery is the primary cause of a performance problem and

    that it will perform better if it utilizes an index. So, you install an /*+ INDEX(zip z5) */ hint, run another EXPLAIN

    PLAN to confirm that the hint was processed, and then run a test case if the execution plan changed.

    Pay little heed to the differing COST values on the plan outputs; that is what the cost-based optimizer has already

    attempted to do! You might possibly find a faster plan that has a higher cost than a slower plan; that is

    symptomatic of poor information (configuration, table statistics, system statistics or data distribution) being provided

    to the CBO.

  • 8/13/2019 Oracle SQL Perfomance

    9/13

    If the hint provides improved results, you are not done! Now the root cause must be determined. Often, it will be

    because statistics on the index or table are missing or stale. Gather fresh statistics on all tables (and their indexes)

    that participate in the query, and see if that has an impact on the execution plan. If it does not, consider analyzing

    a 10053 trace on the query.

    Monitor V$SESSION_LONGOPS or V$SESSION_WAIT

    For a query that runs several minutes or more, periodic monitoring of V$SESSION_LONGOPS or V$SESSION_WAIT

    might provide some insight into what is really happening in a general sense. Is the query spending a lot of time

    accessing data, or joining data, or grouping it (as evidenced by lengthy sort operations)?

    While the insight gained might be marginally useful, the approach is hit or miss and is not particularly thorough.

    More importantly, it is difficult to divine which hint or other optimization approach will best remedy the problem.

    Sometimes, the observed bottleneck can be correlated to a specific step in the EXPLAIN PLAN, and then a hypothesis

    can be tested.

    Examine trace output from events 10053 and 10046

    Trace outputs from the Oracle kernel, gathered while running the problem query, are perhaps the best and most

    thorough way to determine conclusively what the cost-based optimizer is thinking and doing when planning and

    executing the query.

    Using the event 10053 trace: See What Oracle is Thinking

    The 10053 event provides a comprehensive, quantitative journal of the optimizer decision paths used to choose an

    execution plan for a query. Sections of this trace include the query itself, parameter values used by the optimizer,

    base statistical information on the tables and critical columns comprising the query, access paths under

    consideration, general plans (join methods and orders), recosting for special features and a final result. Oracle

    Corporation publishes very little information about this event; however, detailed information about event 10053

    trace output is available in an excellent paper by Wolfgang Breitling [1]. A recommended method for enabling this

    event within a session is:

    alter session set tracefile_identifier='RC_CBO';

    alter session set events '10053 trace name context forever, level 1';

    Following these two commands, run either the problem query or an explain plan for the problem query. Look for the

    tracefile in the user_dump_dest directory; it can be readily identified by its tracefile_identifier (in this case,

    RC_CBO). Browse it, attempt to understand as much of it as you can, hint your query, and start the tracing process

    over again. It can be very helpful to have both tracefiles (before and after hinting) and their corresponding EXPLAIN

    PLAN outputs to get an overview of how the hint is handled by the optimizer.

    Using the event 10046 trace: See What Oracle is Doing

    The 10046, or SQL trace, event can be used along with the Oracle tkprof trace formatting utility or with Trace

    Analyzer [6i] (downloadable from MetaLink) to understand in detail where time is being spent in the execution of a

    problem query. The Trace Analyzer provides a timing graph formatted identically to an EXPLAIN PLAN output, so

    that actual run times can be correlated to the steps in the execution plan. Consider this query:

    select name, city, state from pub78

    where (city,state) in

    (select city,state from pub78

    group by city,state having count(*)=1);

  • 8/13/2019 Oracle SQL Perfomance

    10/13

    When traced, and then run through the Trace Analyzer, this output is presented:

    | Rows Row Source Operation

    | ------------ ---------------------------------------------------

    | 12645 HASH JOIN (cr=8990 pr=382 pw=382 time=14.48)

    | 12880 .VIEW (cr=4432 pr=382 pw=382 time=7.86)

    | 12880 ..FILTER (cr=4432 pr=382 pw=382 time=7.79)

    | 34061 ...SORT GROUP BY (cr=4432 pr=382 pw=382 time=7.68)

    | 614578 ....TABLE ACCESS FULL OBJ# PUB78 (cr=4432 pr=0 pw=0 time=1.95)

    | 614578 .TABLE ACCESS FULL OBJ# PUB78 (cr=4558 pr=0 pw=0 time=1.89)

    Explain Plan

    ---------------------------------------------------------------

    ...7 SELECT STATEMENT (COST=2620 CARD=2576 BYTES=172592 IO_COST=2620 )

    ...6 .HASH JOIN (COST=2620 CARD=2576 BYTES=172592 IO_COST=2620 )

    ...4 ..VIEW OF 'SYS.VW_NSO_1' (COST=1794 CARD=6146 BYTES=122920 )

    ...3 ...FILTER

    ...2 ....SORT (GROUP BY) (COST=1794 CARD=6146 BYTES=79898 IO_COST=1794 )

    ...1 .....TABLE ACCESS (FULL) OF 'RANDY.PUB78' (COST=673 CARD=614578 BYTES=7989514 IO_COST=673 )

    ...5 ..TABLE ACCESS (FULL) OF 'RANDY.PUB78' (COST=673 CARD=614578 BYTES=28885166 IO_COST=673 )

    While the two full-table scans on PUB78 would typically arouse concern, this output indicates that over half of the

    query run-time is a result of the GROUP BY operation, substantially more than the total elapsed time for both full-

    table scans.

    To get a trace of your own SQL session, the following statements should be included preceding the SQL under

    analysis:

    alter session set tracefile_identifier='RC_PROF';

    alter session set sql_trace=TRUE;

    To also see wait events (recommended!) use this alternative invocation, instead:

    alter session set tracefile_identifier='RC_PROF';alter session set events '10046 trace name context forever, level 8';

    Look for files with the tracefile_identifier (in this case, RC_PROF) in the user_dump_dest directory, and apply those

    files to the formatter of your choice according to its documented procedures.

    Whats So Bad About Hints?

    Many respected Oracle experts have published their serious qualms about the use of hints, describing hints as a last

    resort methodology, and something to be avoided or even prohibited in critical environments. These objections

    have merit, and they should be considered when using hints for any purpose other than self-instruction, testing

    hypotheses or debugging.

    If you like the rule-based optimizer, youll love hints. The thrust behind this statement is that hints impair the CBOfrom doing what it is supposed to be doing: optimizing! You might stumble across a hint that yields really fast

    execution on todays data volumes, relative proportions and data skews, but then youll never know if a better, more

    scalable plan would have been found by the CBO as data volumes increase. The presence of hints in a production

    query might guarantee that the plan will remain unchanged, but that does not guarantee that performance will

    always be good!

    Upgrading is a hassle with hints. Because the CBO undergoes refinement with each Oracle release, the

    appropriateness of hints ensconced in views, PL/SQL, Java and stored SQL scripts must be evaluated with each

  • 8/13/2019 Oracle SQL Perfomance

    11/13

    RDBMS software upgrade. Just as hints can mask downside performance issues, they can equally as well mask

    dramatic, upside performance opportunities that are delivered in nearly every new Oracle release.

    Hints inhibit portability. The really fast results you could achieve by fully hinting queries on your development

    system might not be reproduced successfully in every environment. Differences in hardware, OS configuration and

    database configuration can cause a hinted query to run terribly poorly when ported to a different environment.

    Hints are inscrutable. Mere presence of hints is sure to decrease readability and pertinence of a query to any

    developer or business analyst. The clutter of hints in a query might help the CBO work faster, but it wont help

    people work faster.

    Hints cover up sloppy practices. Pervasive use of hints on a database likely is symptomatic of deeper, unresolved

    issues. These include stale or missing object statistics, suboptimal database configuration, poorly written queries

    and even deficient application or database design. So, after writing a hint, take a hint: fix the root cause!

    The bottom line is that hints impose unnatural rigidity on the cost-based optimizer. Rigidity can be helpful during

    diagnosis of a problem, but in the long run, it can be profoundly detrimental to the scalability and adaptability of

    your environment.

    So, no hints in production, right?

    Your organizational best practices should govern, but not entirely prohibit, the deployment of hinted queries in a

    production environment. These are circumstances where hints might legitimately be used in production:

    As a tourniquet, to resolve temporarily a critical production issue. Be sure to revisit the emergency useof the hint at a later time. If possible, use an adequately scaled test or production support environment to

    investigate a durable solution, so that the hint becomes unnecessary for maintaining adequate performance

    and service levels.

    In a prior section captioned Hint Selection Strategies, three hints were identified as having reasonablydeterministic behavior and measurable downside risk. These hints are:

    o APPENDo DRIVING_SITEo

    FIRST_ROWS As part of a carefully orchestrated and tested migration, preferably including stored outlines for plan

    stability, rather than migrating explicitly hinted SQL text.

    What do Stored Outlines have to do with Hints?

    Plenty. Oracle uses hints to record stored plans. Accordingly, the stored outline mechanism can be a satisfactory

    way to manage and migrate carefully screened hints into production, as part of a deliberate value decision favoring

    performance determinacy, or plan stability, instead of the best obtainable throughput.

    Stored outlines are also useful when moving carefully optimized SQL from a rule-based to a cost-based environment.

    Finally, stored outlines are an excellent way to provide hints to queries that would otherwise be inconvenient or

    inadvisable to modify, including stored SQL delivered with ERP and other third-party packages, as well as

    inaccessible SQL imbedded or generated in various applications, such as PeopleSoft or Crystal Reports.

    Bear in mind that with the use of plan stability, you will continue to have rigidity, impaired scalability and other

    adverse issues that come with keeping hints around, albeit in a better managed and documented framework. Stored

    outlines should be periodically revisited to confirm that superior query execution plans are not being suppressed by

    use of plan stability.

  • 8/13/2019 Oracle SQL Perfomance

    12/13

    Alternatives to Hints

    Think of most hints as analogous to diapers, crutches, debuggers or training wheels they are indispensable in the

    short run, but you certainly wouldnt choose to use them all of the time! So, once youve obtained satisfactory

    performance from a problem query using a hint, what is the next step?

    1) Be sure that all tables participating in the problem query have current statistics. Run DBMS_STATS to gather new

    statistics, if necessary. Unless the tables are immense, specify computed, rather than estimated statistics. Be sure

    that all indexes also have current statistics. Then, evaluate the problem query again without the hint.

    2) [DBA] Confirm that system statistics are periodically measured and recorded. See MetaLink Note 149560.1 [6j]

    3) Attempt to adjust session CBO parameters instead of, or in combination with, using hints. Consult this list of

    parameters used by the optimizer, understand them and adjust them appropriately:

    optimizer_mode optimizer_index_caching (default value is usually deficient, see [2]) optimizer_index_cost_adj (default value is often deficient, see [2]) optimizer_dynamic_sampling optimizer_max_permutations hash_join_enabled db_file_multiblock_read_count (used differently between Oracle8i and Oracle9i) sort_area_size and hash_area_size (Oracle8i and prior)

    4) [DBA] Ensure that database CBO spfile parameters, especially optimizer_mode, compatible,

    optimizer_features_enable, optimizer_index_caching and optimizer_index_cost_adj, are established for optimal

    benefit to the entire instance.

    5) Carefully observe the cardinality values in the querys EXPLAIN PLAN and 10053 trace. If there is a data

    distribution (skew) issue, consider gathering statistics for column histograms.

    6) If possible, consider expressing the query differently. The CBO is rarely confounded by the mere order of tables in

    a FROM list or by predicate order or transitivity. Increasingly, it has the ability to recognize and transform specific

    suboptimal constructions such as OR predicates. Nevertheless, expressing lengthy or complex queries in an entirely

    different way sometimes results in improvements to the execution plan.

    Conclusion

    Query hints provide a convenient, ready-to-use means to manipulate the cost-based optimizer for a specific problem

    query. Hints can be useful for debugging a database or application issue, for testing SQL performance scenarios,

    and for learning how the optimizer works. With discipline and restraint, hints can even be used for advantage in

    production environments.

    Because hints constrain the optimizers freedom to explore a full range of execution plans, they inhibit scalability and

    optimal performance when they remain in a SQL statement over a period of time. Therefore, hints should not be

    regarded as a solution to performance issues, but they should be considered as an important tool for achieving top

    query performance.

  • 8/13/2019 Oracle SQL Perfomance

    13/13

    References[1] Breitling, Wolfgang; A Look Under the Hood of CBO: The 10053 Event. http://www.centrexcc.com

    [2] Gorman, Tim; The Search for Intelligent Life in the Cost-Based Optimizer. http://www.evdbt.com

    [3] Green, Connie Dialeris; Oracle9i Database Performance Tuning Guide and Reference, Release 2 (9.2),

    Chapter 5. October 2002, Oracle Corporation Part No. A96533-02.

    [4] Harrison, Guy; Oracle SQL High-Performance Tuning, Second Edition. 2001 Prentice-Hall, ISBN: 0-13-

    012381-1.

    [5] Holdsworth, Andrew; Oracle9i Database Performance Planning. March 2002, Oracle Corporation Part No.

    A96532-01.

    [6] Oracle Support Site (subscription required). http://metalink.oracle.com. Resources:

    [6a] Note: 29236.1 QREF: SQL Statement Hints

    [6b] Note: 50607.1 How to specify and index hint

    [6c] Note: 62364.1 Hints and subqueries

    [6d] Note: 69992.1 Why is my hint ignored?

    [6e] Note: 73489.1 Affect of Number of Tables on Join Order Permutations

    [6f] Note: 122812.1 How to Tune a Query that Cannot be Modified

    [6g] Note: 225598.1 How to Obtain Tracing of Optimizer Computations (EVENT 10053)

    [6h] Note: 35934.1 Cost Based Optimizer - Common Misconceptions and Issues

    [6i] Note: 224270.1 Trace Analyzer: Interpreting Raw SQL Traces Generated by Event 10046[6j] Note: 149560.1 Collect and Display System Statistics (CPU and IO) for CBO usage

    About the Author

    Randy Cunningham is a consultant with SageLogix, Inc., based in Englewood, Colorado, USA. He has worked with

    Oracle since version 4, and has been consulting exclusively to clients using Oracle products for the past eight years.

    His primary professional focus is on the architecture, implementation and performance optimization of ERP and data

    warehousing applications, with a secondary emphasis on database replication techniques.