You are on page 1of 97

An Introduction To Oracle SQL Tuning

Chris Adkin 30th May 2008

01/05/2012

1

Some Inspirational Thoughts Before We Begin . . .

The following Ask Tom excerpt comes in response to a “You Asked Can u give a methodology of tuning the sql statements.” question. The link to the full answer is at: http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_I D:8764517459743 Despite being five years old, in the intervening time, artificial intelligence has not been built into the RDBMS where by it can re-write your SQL such that it will run in the most efficient manner possible. Advisors take some of the leg work out of tuning and the tools such as DBMS_XPLAN, v$ views etc constantly change, evolve and improve, however SQL tuning and writing efficient SQL is not a prescriptive process that can be captured in a process. I will however try to present useful techniques and good practise to „demystify‟ some of the „art‟ behind this.
2

Some Inspirational Thoughts Before We Begin . . .

1.1 Efficient SQL This was probably the hardest part of the book to write - this chapter. That is not because the material is all that complex, rather because I know what people want - and I know what can be delivered. What people want: The 10 step process by which you can tune any query. What can be delivered: Knowledge about how queries are processed, knowledge you can use and apply day to day as you develop them. Think about it for a moment.
3

Oh don't get me wrong. we would write a program to do it. offer to add hints to the query to try other access plans. . What they do is primarily recommend indexing schemes to tune a query.Some Inspirational Thoughts Before We Begin . suggest materialized views. SQL Navigator and others.000.Oracle Enterprise Manager with its tuning pack. .000 step process by which any query can be tuned (or even X% of queries for that matter). 4 .  If there were a 10 step or even 1. there are many programs that actually try to do this .

which if they were universally applicable . They offer "rules of thumb" (what I generally call ROT since the acronym and the word is maps to are so appropriate for each other) SQL optimizations . These tuning tools use a very limited set of rules that sometimes can suggest that index or set of indexes you really should have thought of during your design.it rewrites our queries all of the time. the cost based optimizer does that already . .Some Inspirational Thoughts Before We Begin .  They show you different query plans for the same statement and allow you to pick one. In fact.the optimizer would do it as a matter of fact. 5 . .

the optimizer would incorporate it all and we would not be having a discussion about this topic at all. . .  I'll close this idea out with this thought .if there were an N step process to tuning a query. it will be able to take our SQL. to writing efficient SQL . It is like the search for the holy grail maybe someday the software will be sophisticated enough to be perfect in this regards. understand the question being asked and process the question . 6 .Some Inspirational Thoughts Before We Begin .rather then syntax.

Section 1 Mechanics Of The Cost Based Optimizer 01/05/2012 7 .

Transparent to application and users. Devises the best plan for executing a query based on cost. Around since Oracle 7. except when the „wrong‟ plan is selected.What Is The Optimizer      I will focus on the Cost Based Optimizer. 8 . The stages of optimisation will be covered on the next set of slides.

these are affectively different plans for the same SQL text when different variables are supplied (an over simplification. but basically what happens). A parsed SQL statement (cursor) can have multiple child cursors. a hard parse or optimisation takes place (a gross over simplification. prior releases use a combination of SQL address and hash value. 9 . If a query does not exist in parsed form in the shared pool.Stages Of Optimisation     On 10g parsed SQL statements are assigned unique identifiers called sql ids. Oracle can also perform optimisations at run time. but basically what happens).

Stages Of Optimisation  Establish the environment Ascertain what parameters are set  Ascertain what bug fixes are in place based on the setting of the compatible parameter   Query transformation Sub query un-nesting  Complex view merging  Set Join Conversion  Predicate move around  10 .

11 . Single table access cardinality estimation.  Record will be kept of the best join order maintained so far. Join order consideration.Stages Of Optimisation    Establish the base statistics of all the relevant tables and indexes.

refer to:v$sys_optimizer_env  v$ses_optimizer_env  V$sql_optimizer_env  12 .What Influences The Cost Based Optimizer ?    Object statistics Object data types Oracle initialisation parameters.

76881 10 4096 1* select * from sys.aux_stats$ SQL> / SYSSTATS_INFO STATUS SYSSTATS_INFO DSTART SYSSTATS_INFO DSTOP SYSSTATS_INFO FLAGS SYSSTATS_MAIN CPUSPEEDNW SYSSTATS_MAIN IOSEEKTIM SYSSTATS_MAIN IOTFRSPEED SYSSTATS_MAIN SREADTIM SYSSTATS_MAIN MREADTIM SYSSTATS_MAIN CPUSPEED SYSSTATS_MAIN MBRC SYSSTATS_MAIN MAXTHR SYSSTATS_MAIN SLAVETHR 13 .What Influences The Cost Based Optimizer ?  System statistics:COMPLETED 11-26-2006 19:53 11-26-2006 19:53 1 1081.

In Oracle 9i. The optimizer cost model can be set via _optim_cost_model. Stats that are not populated in aux_stats$ only appear after system statistics have been gathered. Until this came along the optimizer did not take into account CPU performance nor the difference in performance between single and multi block reads. 14 . no system statistics are present.What Influences The Cost Based Optimizer ?       System statistics facilitate something called the “CPU costing model” introduced in Oracle 9i. In 10g “out of the box” statistics called “no workload” statistics are provided. set this to IO or CPU.

What Influences The Cost Based Optimizer ?  !!! Warning !!! You have to be very careful when gathering system statistics.oracle.com/technology/software/tech/orion/index.  This can seriously skew a plan‟s costings.html   15 . Oracle supply an “I/O calibration” tool called Orion which might help here: http://www.  If you have any I/O sub system with a cache you can end up getting single block and multi block I/O times that reflect the speed of the cache rather than the under lying disks.

col_usage$ in the data dictionary will be updated whenever a statement is parsed.  DBMS_STATS uses this in order to determine whether a histogram should be created on a column when size = AUTO is specified in the method_opt.What Influences The Cost Based Optimizer  SQL Usage Unless the NO_MONITOR hint is used.  Oracle can get confused with what to do for columns where the LIKE and col_usage$ and hence not create histograms when size auto is specified.  16 .

presence of indexes. constraints etc . 17 .What Influences The Cost Based Optimizer  Hints and profiles SQL hints  Stored out lines (essentially hints)  SQL profiles as created by the Oracle 10g tuning advisor   Objects. . partitioning. .

Section 2 A Plan Of Attack For Investigating A Bad Plan 01/05/2012 18 .

Identify The SQL To Be Tuned  Many ways of doing this:Automatic Database Diagnostic Manager $ORACLE_HOME/rdbms/admin/addmrpt  Automatic Workload Repository reports $ORACLE_HOME/rdbms/admin/awrrpt  Toad  SQL Tuning Advisor $ORACLE_HOME/rdbms/admin/sqltrpt  19 .

elapsed_time.   20 . user_io_wait_time. for previous releases this a combination of hash value and sql address. cpu_time.A Simple Script For Identifyng SQL To Be Tuned  SELECT * FROM (SELECT sql_id. As a first pass tuning try running the SQL tuning advisor on the query. my preferred way of doing this is via the sqltrpt script in $ORACLE_HOME/rdbms/admin. concurrency_wait_time FROM v$sql ORDER BY elapsed_time DESC) WHERE rownum <= 10 In 10 onwards SQL statements are uniquely identified by sql ids.

2. more on this later. more on this later.0. 21 .0. Lack of appropriate indexes to support your query Bugs in the optimizer. Optimizer flaws. such as the predicate independence assumption. there are the best part of 100 bug fixes related to the optimizer in 10.4. SQL that is “optimizer unfriendly”.Causes Of Poor Performance       Stale or missing statistics (includes missing histograms). SQL that is inefficient by design.

Misuse or poor use of Oracle features. 22 . table type or partitioning schemes that are not conducive to good performance with the query mix you are running.Causes Of Poor Performance     Index. Abuse of the Oracle optimizer environment. Poor schema design.

 23 .  Do not confuse something that is running slow because it has an abnormally high workload for something that is inefficient at what it does.  Is the part of the application running slowly because it is not designed to deal with the shape and / or size of the data it is processing ?.The Tuning Ethos  Ask the following questions:Has what I need to tune ever ran „fast‟. if so what has changed in the environment.

Try to use a clean environment without factors that may skew your results. a global change such as a change to an initialisation parameter is unlikely to address the root cause of the issue and it may cause performance regression for queries that are currently performing well.The Tuning Ethos  When tuning     Only make one change at a time so as to be able to accurately gauge what affects your query.g. for accurate and consistent response times avoid database and servers which are being used by other users if possible. Try to make the scope of any changes match the scope of the problem.g. 24 . e. if you have a problem with one query. e. Use realistic test data.

 Schema design changing.g.The Tuning Ethos  Tuning a piece of SQL may result in:Indexes being added or modified.g. heap to index organized tables.  Statistic gathering regimes being modified.  Object types being changed.  SQL being re-written.  25 . e. e.  The use of hints. extra columns added to tables in order to reduce numbers of joins.

g. col NOT IN (1.  Recommends SQL profiles. .  26 . . col <>. . e.  Identifies parts of statements where view mergining cannot take place.Tuning Is Dead We Have The Tuning Advisor !!!  Based on my experience this:Recommends indexes  Identifies stale statistics  Notifies you of Cartesian joins  Spots predicates not conducive to the efficient use of indexes. 2.

27 . The use of SQL profiles can cause a problem if your base data changes such that they are no longer relevant. It is the best tool of its type that Oracle have produced to date. This is good for a first pass at identifying more obvious causes of a query running sub optimally.Tuning Is Dead We Have The Tuning Advisor !!!      If the tuning advisor does anything else. I am yet to see it. SQL profiles are enhanced hints that provide the optimizer with extra information with which to get cardinality estimates correct with. it is not artificially intelligent and it smacks of the „ROT‟ tools that Tom Kyte mentioned.

A Simple „Methodology‟ For Query Tuning     Despite what the Oracle marketing machine may say. The tuning advisor in its 10g incarnation is no substitute for a knowledgeable DBA at best it semi automates the task of tuning. Some people instantly assume that because a plan contains a full table scan that the execution plan is therefore bad. tuning is not a prescriptive process. This is an out dated method of tuning with origins based around the rule based optimizer. 28 .

29 . Queries return most of the columns in a table. The indexes you think the query should use have poor clustering factors.e. I. Reasons for full table scans might include:    Queries that use un-selective predicates.Good And Bad Plans   Do not automatically jump to the conclusion that a bad plan contains full table scans and a good plan only uses index range scans. result in all or a large proportion of a tables data being returned. The table is „small‟ in size‟.

30 . you will not always be asked for the same information or to use the same diagnostic tools depending on who the service request is assigned to. This may change with the DBMS_SQLDIAG package in 11g.A Simple „Methodology‟ For Query Tuning     What I will outline is a plan of attack for tackling query issues. There is no such thing as a definitive tuning methodology as alluded to by Tom Kyte. aka the SQL test case builder. Even when Oracle support is engaged with a tuning related service request.

Nothing daft has been done to abuse the optimizer environment. 31 . I will assume:    All reasonable indexes. . Oracle has produced sub optimal plans due to discrepancies between predicated cardinalities and actual cardinalities. . this would require a different presentation entirely.A Simple „Methodology‟ For Query Tuning  My “plan of attack” will not cover the writing of efficient SQL. are in place. partitioning schemes etc .

Obtain the execution plan for your query  If you run an explain plan from the SQL prompt this will give you the plan that Oracle predicts the statement will use.:SQL> EXPLAIN PLAN FOR SELECT * FROM dual SQL> SELECT * FROM table(dbms_xplan.display_cursor(‘sqlid’)) Sql ids are new to Oracle 10g and uniquely identify parsed SQL statements 32 .display)  A better way of explaining the execution plan is by taking it straight from the shared pool:SQL> SELECT * FROM table(dbms_xplan.e. I.A Simple „Methodology‟ For Query Tuning 1.

DISPLAY_AWR(<your SQL id goes here>)  If you use explain plan. ‘ALLSTATS LAST’)  Obtain the plan from the shared pool SELECT * FROM TABLE(DBMS_XPLAN.A Simple „Methodology‟ For Query Tuning 1. Where possible obtain the plan after running the query: SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL. this may not necessarily but what the plan is when the query runs due to such things as bind variable peeking.DISPLAY_CURSOR(<your SQL id goes here>)  Obtain the plan from the workload repository SELECT * FROM TABLE(DBMS_XPLAN. 33 . Obtain the execution plan for your query   The DBMS_XPLAN package is the best tool here. this will give you what the optimizer predicts the plan will be. NULL.

"LOSAL") 6 ."SAL"<="SALGRADE"."SAL">="SALGRADE".Understanding A Basic Execution Plan PLAN_TABLE_OUTPUT ----------------------------------------------------------------| Id | Operation |Name |Rows|Bytes|Cost | ----------------------------------------------------------------| 0 | SELECT STATEMENT | | | | | | 1 | NESTED LOOPS | | | | | | 2 | NESTED LOOPS | | | | | | 3 | TABLE ACCESS FULL | SALGRADE| | | | |* 4 | TABLE ACCESS FULL | EMP | | | | | 5 | TABLE ACCESS BY INDEX ROWID| DEPT | | | | |* 6 | INDEX UNIQUE SCAN | DEPT_PK | | | | ----------------------------------------------------------------Predicate Information (identified by operation id): --------------------------------------------------- 4 .access("EMP"."DEPTNO") 34 .filter("EMP"."DEPTNO"="DEPT"."HISAL" AND "EMP".

the table for which the filter predicates will reduce the most. not always an issue. .e. Is the most restricted table the „driving‟ table. this is the first table in the join order and usually the table that is furthest indented into the plan. but could indicate that the join order is incorrect Continued . Visually sanity check your execution plan    Does the plan contain any Cartesian joins ?.A Simple „Methodology‟ For Query Tuning 2. 35 . Is the access for the driving table via a full table scan. I. .

APPMT_START_TIME < to_date(:4. .ID_JOB )) ---------------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost | ---------------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | 151 | 1187 | | 1 | HASH UNIQUE | | 1 | 151 | 1187 | | 2 | NESTED LOOPS | | 1 | 151 | 1176 | | 3 | MERGE JOIN CARTESIAN | | 1 | 104 | 684 | | 4 | NESTED LOOPS | | 1 | 51 | 665 | |* 5 | INDEX FAST FULL SCAN | TR_CONSUMPTION_HISTORY_IX2 | 1 | 5 | 663 | |* 6 | TABLE ACCESS BY INDEX ROWID| TR_JOB | 1 | 46 | 2 | |* 7 | INDEX UNIQUE SCAN | TR_JOB_ID_PK | 1 | | 1 | | 8 | BUFFER SORT | | 32474 | 1680K| 682 | | 9 | TABLE ACCESS FULL | TR_OFFCYCLE_JOB_DETAILS | 32474 | 1680K| 19 | |* 10 | TABLE ACCESS FULL | TR_CYCLIC_JOB_DETAILS | 1 | 47 | 492 | ---------------------------------------------------------------------------------------------- Continued .ID_JOB=A.VISIT_DATE_TO > to_date(:7.SD_JOB_STATUS = :2 AND B.'yyyy-MM-dd hh24:MI:SS') AND F. 36 . Visually sanity check your execution plan  Are you battling against the schema design.SD_READING_TYPE = :3 AND (( F.'yyyy-MM-dd hh24:MI:SS') AND F.'yyyy-MM-ddhh24:MI:SS') AND C.ID_JOB FROM TR_JOB A.A Simple „Methodology‟ For Query Tuning 2.ID_JOB=A. TR_CYCLIC_JOB_DETAILS C. .ID_JOB AND A. an example:SELECT DISTINCT A.'yyyy-MM-dd hh24:MI:SS') AND C.ID_JOB ) OR ( C.APPMT_END_TIME > to_date(:5.ID_SERVICEPOINT =:1 AND A. TR_CONSUMPTION_HISTORY B WHERE A. TR_OFFCYCLE_JOB_DETAILS F.VISIT_DATE_FROM < to_date(:6.ID_JOB = B.

specifically if one of the branches evaluates to TRUE the join predicates do not get performed for two tables. note that the only reason we are going to the TR_CONSUMPTION_HISTORY table is to get the contents of the sd_reading_type column. We have an index fast full scan (index equivalent of a full table scan) on TR_CONSUMPTION_HISTORY_IX2. Visually sanity check your execution plan In the previous example there are two issues:  There is a Cartesian join due to the OR condition. 37 .A Simple „Methodology‟ For Query Tuning 2.

38 . supply the sql id for your query and the tuning advisor will go to work for you. you can run the sqltrpt script from $ORACLE_HOME/rdbms/admin. . Do appropriate indexes exists. Check the ‘environment’ is correct for the query:  Are statistics up to date for all the objects used by the query. . Continued .A Simple „Methodology‟ For Query Tuning 3. this will also highlight any tables with stale statistics.

A Simple „Methodology‟ For Query Tuning
3. Checking the ‘environment’ is correct for the query From Greg Rahn of the Oracle Real World performance group:I think it’s important to understand what variables influence the Optimizer in order to focus the debugging effort. There are quite a number of variables, but frequently the cause of the problem ones are: (1) non default optimizer parameters and (2) nonRepresentative object/system statistics. Based on my observations I would say that the most abused Optimizer parameters are:
  

OPTIMIZER_INDEX_CACHING OPTIMIZER_INDEX_COST_ADJ DB_FILE_MULTIBLOCK_READ_COUNT
39

A Simple „Methodology‟ For Query Tuning
3. Checking the ‘environment’ is correct for the query
Many see setting these as a solution to get the Optimizer to choose an index plan over a table scan plan,but this is problematic in several ways:  This is a global change to a local problem Although it appears to solve one problem, it is unknown how many bad execution plans resulted from this change.  The root cause of why the index plan was not chosen is unknown, just that tweaking parameters gave the desired result  Using non-default parameters makes it almost impossible to correctly and effectively troubleshoot the root cause

40

A Simple „Methodology‟ For Query Tuning
4. Understand your data, how ‘Selective’ is it ?

Are the predicates and variables used in your statement going to retrieve a „significant‟ or „small‟ proportion of rows from the queries base tables ?. The following predicates come from a query I have investigated the performance of:UPPER (a.walkroute_reviewed_flag) = 'Y' ( ( a.sd_service_type = '10000' AND a.sd_servicepoint_status = '10001' ) OR ( a.sd_service_type = '10001' AND a.sd_occupied_status = '10001' AND a.sd_servicepoint_status = '10001' ) OR a.sd_servicepoint_status = '10000' OR a.sd_servicepoint_status = '10003‘

It returns a third of the data in the AD_SERVICE_POINT table, therefore if the clustering factors of the appropriate indexes are not particularly good, a full table scan is probably the most efficient way to retrieve the relevant data.41

when bad. detailed analysis of access path costing may need to be performed.  This method of trouble shooting is sometimes referred to as “Tuning by cardinality feedback”.  If predicted cardinalities are accurate.  Bad cardinality estimates. 42 . Are the predicted cardinalities for for the execution plan accurate  If the predicted cardinalities for the row sources in the plan are accurate and the appropriate access paths (indexes) exist. the optimizer will usually come up with a „good‟ plan.A Simple „Methodology‟ For Query Tuning 5. will be out by an order of magnitude and „ripple‟ throughout the rest of the place.

To start down this route of tuning we need to obtain the SQL text for the query in question along with any bind variable values it uses. the DBMS_XPLAN package.“Tuning By Cardinality Feedback”    Generally speaking if the predicated cardinalities and actual cardinalities for a row source are close. the optimizer will pick the best plan for the query. The best way of doing this is via one of the most useful tools in our tuning „toolbox‟. 43 .

“Tuning By Cardinality Feedback”      “Tuning by cardinality feedback” is borrowed from one of the reviewers of Jonathan Lewis‟s Cost Based Fundamental‟s book: www. This is also endorsed by the Oracle Real World Performance Group http://structureddata. this is a really easy method to use. Other Oracle professionals may call this something different.com/Tuning by Cardinality Feedback.centrexcc.pdf. 44 . I would not advocate playing around with density settings as this may fix queries suffering from the “Predicate Independence Assumption” but cause bad plans for other queries.org/2007/11/21/troubleshooting-bad-executionplans/ With the GATHER_PLAN_STATISTICS hint and “ALLSTATS LAST” format string in DBMS_XPLAN (Oracle 10g).

:1 (NUMBER): 80310011 Predicate Information (identified by operation id): --------------------------------------------------2 .0.'TYPICAL +PEEKED_BINDS')) 2 / SQL_ID ft33c3agapy0k.cpu costing is off (consider enabling it) 45 .access("ID_PACK"=:1) Note ----.display_cursor('ft33c3agapy0k'. child number 0 ------------------------------------UPDATE TR_CYCLIC_WORK_PACK SET PACK_JOB_COUNTER =PACK_JOB_COUNTER +1 WHERE ID_PACK=:1 Plan hash value: 115273857 -------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost | -------------------------------------------------------------------------| 0 | UPDATE STATEMENT | | | | 2 | | 1 | UPDATE | TR_CYCLIC_WORK_PACK | | | | |* 2 | INDEX UNIQUE SCAN| TR_CYC_WORKPACK_PK | 1 | 9 | 1 | -------------------------------------------------------------------------Peeked Binds (identified by position): -------------------------------------1 .Obtaining Your SQL Text + Binds  A trivial example to whet the appetite SQL> select * from table(dbms_xplan.

gather_table_stats(user.cpu costing is off (consider enabling it) 46 .display_cursor(NULL.access("ID_PACK"=:B1) Note ----.ESTIMATE_PERCENT=>NULL. SQL_ID cqnxyqmp08rtu.CASCADE=>TRUE).01 | 4 | |* 2 | INDEX UNIQUE SCAN| TR_CYC_WORKPACK_PK | 1 | 1 | 1 |00:00:00. UPDATE /*+ GATHER_PLAN_STATISTICS */ TR_CYCLIC_WORK_PACK SET PACK_JOB_COUNTER =PACK_JOB_COUNTER +1 WHERE ID_PACK=:b1 / select * from table(dbms_xplan.Checking Predicated Versus Estimated Cardinalities SQL> SQL> SQL> SQL> 2 3 SQL> var b1 number exec :b1 := 803100113 exec dbms_stats.'TR_CYCLIC_WORK_PACK'.'ALLSTATS LAST')).01 | 2 | ---------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------2 .NULL. child number 0 ------------------------------------UPDATE /*+ GATHER_PLAN_STATISTICS */ TR_CYCLIC_WORK_PACK =PACK_JOB_COUNTER +1 WHERE ID_PACK=:b1 Plan hash value: 115273857 SET PACK_JOB_COUNTER ---------------------------------------------------------------------------------------------------| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | ---------------------------------------------------------------------------------------------------| 1 | UPDATE | TR_CYCLIC_WORK_PACK | 1 | | 1 |00:00:00.

Checking Predicated Versus Estimated Cardinalities     The example on the previous slide was the simplest example that can be provided. this inaccuracy in will „ripple‟ throughout the rest of the plan and lead to poor performance. 47 . If nested loop joins are used:starts x E-Rows = A-Rows otherwise E-Rows = A-Rows   Usually for a bad plan the estimated cardinalities will differ from the predicated cardinalities by orders of magnitude. On the next slide a more complex example will be provided. Note that for line 2 the values in the E-Rows and A-Rows columns matched. Line 2 in the execution plan is what is known as a row source.

In 10g dynamic sampling or hints can help here. DBMS_STATS in 10g can produce statistically incorrect estimates of distinct values when auto sampling / sampling is used. 48 .Reasons For Estimated Cardinalities Being Inaccurate  Statistics gathering limitations:    Columns with skewed containing more than 254 distinct values => can be rectified with the DBMS_STATS API. Not possible until 11g to gather statistics on functions unless function based indexes are used. Not possible until 11g to gather statistics on correlated columns. this is due to what is sometimes called “data correlation” or the “predicate independence assumption”. more on this later.

Lack of histograms or histograms with too few buckets on columns with skewed data. During the course of processing data changes such that it no longer reflects the statistics in the data dictionary. in 11g auto sampling gives 100% statistically accurate statistics. dynamic sampling can help here. 49 . a particular problem with „scratch‟ data.Reasons For Estimated Cardinalities Being Inaccurate  None representative statistics:    Statistics are missing or stale. Sampled statistics taken with too small a sample size.

Reasons For Estimated Cardinalities Being Inaccurate  Optimizer unfriendly SQL  Using values in the WHERE clauses with data types which are different to those used by the columns comparisons are being made against. 50 .

51 .Reasons For Estimated Cardinalities Being Inaccurate  Other factors: Optimizer bugs.

#3 If you run into the “Predicate independence assumption” issue this is a tough nut to crack.e.org/2008/03/05/there-is-no-time-like-now-to-use-dynamic-sampling/  #4 Use hints and profiles when all else fails. read this article first:http://structureddata. I. as soon as the data changes. 52 . watch out for the use of functions and expressions.Fixing Bad Cardinality Estimates     Hints may work fine for the data in your database at the time of testing. however. the plan you have forced via hints may no longer be the „best‟ plan. #2 write SQL that gives the optimizer a fighting chance of gets cardinality estimates correct. look at using dynamic_sampling. #1 In the first place your stats should be correct.

they can have the side affect of increased hard parsing through bind peeking. !!! A histogram with only two end points stores no information on data distribution !!!. 53 . Only create histograms where they are required.Fixing Bad Cardinality Estimates     Histograms should be present for columns with skewed data with the correct number of buckets. Unless a hint is for DYNAMIC_SAMPLING only use access path hints as a last resort.

Section 3 Worked Examples Of Tuning BY “Cardinality Feedback” 01/05/2012 54 .

f.address_line1.id_servicepoint. 'N') AND a. a.id_best_address(+) AND c. b.out_post_code || ' ' || b. ad_customer c.ID AS customerid.do_not_visit_flag. b. b.description.incomp_postcode IN ('n'.address_line7.address_line11. d. g.target_read_date.address_line9.customer_ref. b. a.address_line4 AS best_address_line4.*. sd_customer_type f.id_personal_details AND c.business_name. ad_personal_details d.id_servicepoint NOT IN ( SELECT id_servicepoint FROM tr_job WHERE sd_job_status IN (10003.sd_customer_type. g.address_line12. 10003)) AND UPPER (b. g.id_personal_details = d. ROWNUM rnum FROM (SELECT DISTINCT a. b.address_line7 AS best_address_line7. 'WALKROUTEREFID' AS walkrouterefid. c.out_post_code || ' ' || g.ID AND b. c. c.in_post_code ELSE g. b.address_line2. b. g.address_line1 AS best_address_line1.address_line8.address_line5 AS best_address_line5. b. c.address_line11 AS best_address_line11.address_line2 AS best_address_line2. d. a. a.in_post_code. f. g.in_post_code AS best_in_post_code.address_line4.out_post_code. c.id_personal_details. b.address_line9 AS best_address_line9. CASE WHEN b.id_best_address = g. 10011) AND sd_job_type IN (10002.address_line10 AS best_address_line10.id_customer = c.trading_name. b.better_address_flag = 'N' THEN b.id_customer. b.id_portfolio_address AND a.address_line3 AS best_address_line3.address_line3.surname. g. ad_portfolio_address b.servicepoint_refid. g. g. b.address_line10.in_post_code END AS out_in_postcode FROM ad_service_point a.out_post_code) = 'FY1' ORDER BY out_in_postcode) a WHERE ROWNUM <= 26) WHERE rnum > 0 55 . b. g.address_line5.id_customer AND a. g.address_line8 AS best_address_line8. g. b. g.incomp_postcode.sd_customer_type = f. b.address_line6 AS best_address_line6.id_portfolio_address = b. d. ad_best_address g WHERE a.address_line12 AS best_address_line12.address_line6. g.out_post_code AS best_out_post_code. b.A „Simple‟ Example Of Bad Cardinality Estimate Trouble Shooting SELECT * FROM (SELECT a.better_address_flag.forename.middlename. g.

"ID_PORTFOLIO_ADDRESS") 12 .filter((INTERNAL_FUNCTION("SD_JOB_STATUS") AND INTERNAL_FUNCTION("SD_JOB_TYPE"))) 17 .60 | 10 | NESTED LOOPS OUTER | | 1 | 26626 | 43983 |00:00:23.06 |* 16 | INDEX FAST FULL SCAN | TR_JOB_IX13 | 1 | 266K| 3 |00:00:04.30 | 14 | TABLE ACCESS BY INDEX ROWID| AD_BEST_ADDRESS | 43983 | 1 | 825 |00:00:00.36 | 7 | NESTED LOOPS | | 1 | 1 | 43983 |00:00:37.22 |* 19 | INDEX UNIQUE SCAN | SD_CUSTTYPE_ID_PK | 43983 | 1 | 43983 |00:00:00.access("A"."ID_CUSTOMER") 19 .39 ---------------------------------------------------------------------------------------------------Predicate Information (identified by operation id): --------------------------------------------------1 .04 | 13 | TABLE ACCESS FULL | AD_SERVICE_POINT | 1 | 6762K| 6762K|00:00:20.filter("RNUM">0) 2 ."ID_BEST_ADDRESS"="G"."ID_PORTFOLIO_ADDRESS"="B".access("A".11 | 18 | TABLE ACCESS BY INDEX ROWID | SD_CUSTOMER_TYPE | 43983 | 1 | 43983 |00:00:00."ID_CUSTOMER"="C".access("A".66 | |* 9 | HASH JOIN ANTI | | 1 | 1 | 43983 |00:00:36.filter(ROWNUM<=26) 9 .filter((UPPER("B".90 | |* 2 | COUNT STOPKEY | | 1 | | 26 |00:00:38.58 |* 11 | HASH JOIN | | 1 | 26626 | 43983 |00:00:23.filter(ROWNUM<=26) 4 .access("C".09 |* 20 | INDEX UNIQUE SCAN | AD_PERDET_ID_PK | 43983 | 1 | 43983 |00:00:00.43 |* 17 | INDEX UNIQUE SCAN | AD_CUST_ID_PK | 43983 | 1 | 43983 |00:00:01."ID_SERVICEPOINT"="ID_SERVICEPOINT") PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------------------------11 .75 | 6 | NESTED LOOPS | | 1 | 1 | 43983 |00:00:38."ID_BEST_ADDRESS") 16 .access("A".90 | 5 | HASH UNIQUE | | 1 | 1 | 43983 |00:00:38.A „Simple‟ Example Of Bad Cardinality Estimate Trouble Shooting ---------------------------------------------------------------------------------------------------| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time ---------------------------------------------------------------------------------------------------|* 1 | VIEW | | 1 | 1 | 26 |00:00:38."SD_CUSTOMER_TYPE"="F".13 |* 15 | INDEX UNIQUE SCAN | AD_BESTADD_PK | 43983 | 1 | 825 |00:00:00.92 | 8 | NESTED LOOPS | | 1 | 1 | 43983 |00:00:37."INCOMP_POSTCODE"))) 15 ."OUT_POST_CODE")='FY1' AND INTERNAL_FUNCTION("B".90 | | 3 | VIEW | | 1 | 1 | 26 |00:00:38.90 | |* 4 | SORT ORDER BY STOPKEY | | 1 | 1 | 26 |00:00:38."ID") | Buffers | Reads | | | | | | | | | | | | | | | | | | | | 385K| 385K| 385K| 385K| 385K| 385K| 297K| 253K| 165K| 148K| 147K| 564 90832 1 826 | 16759 | 87968 | 2 | | Writ 637 | 637 | 637 | 637 637 0 0 0 | | | | | 139K| 139K| 139K| 139K| 139K| 138K| 138K| 138K| 124K| 107K| 107K| 12M 0 | 0 | 0 | 9005K 6444K 1 16 56 .40 |* 12 | INDEX FAST FULL SCAN | AD_PORTADD_PK | 1 | 26626 | 43983 |00:00:13.

count(*) from user_tab_histograms where column_name in ('SD_JOB_TYPE'.A „Simple‟ Example Of Bad Cardinality Estimate Trouble Shooting   Lets create a histogram on sd_job_type Lets look at the distinct values in the sd_job_type and sd_job_status columns:- SQL> select count(distinct sd_job_type). count(distinct sd_job_status) from tr_job.-------SD_JOB_STATUS 5 SD_JOB_TYPE 2 57 . COUNT(DISTINCTSD_JOB_TYPE) COUNT(DISTINCTSD_JOB_STATUS) -------------------------.---------------------------3 5  1 Now lets look at the histograms on these columns:- select column_name. 'SD_JOB_STATUS‘) 2* group by column_name SQL> / COLUMN_NAME COUNT(*) ---------------.

'TR_JOB'.gather_table_stats(user. 58 SQL> exec dbms_stats.method_opt=>'FOR COLUMNS SD_JOB_TYPE SIZE 3'. We‟ll flush the shared pool.    .estimate_percent=>NULL).A „Simple‟ Example Of Bad Cardinality Estimate Trouble Shooting  The estimated cardinality is going badly wrong on line 16 of the plan. You will see that on line 13 of the plan that the estimated and actual cardinalities are closer. but this illustrates the general principle of tuning by this approach. We now need to look at line 12 on the plan. re run the query and get the estimated and actual cardinalities from the shared pool with DBMS_STATS.

00 | 5 | HASH UNIQUE | | 1 | 1 | 43983 |00:03:23.access("A".access("C".81 |* 18 | INDEX UNIQUE SCAN | AD_CUST_ID_PK | 43983 | 1 | 43983 |00:00:05.access("A"."ID_CUSTOMER") 20 .filter("RNUM">0) 2 ."ID_BEST_ADDRESS"="G".filter(ROWNUM<=26) 4 ."ID_PERSONAL_DETAILS"="D".50 ---------------------------------------------------------------------------------------------------Predicate Information (identified by operation id): --------------------------------------------------1 ."ID_CUSTOMER"="C".00 | |* 2 | COUNT STOPKEY | | 1 | | 26 |00:03:24.06 |* 13 | INDEX RANGE SCAN | TR_JOB_IX3 | 2 | 45251 | 36201 |00:00:00.11 | 11 | INLIST ITERATOR | | 1 | | 3 |00:00:00.00 | 3 | VIEW | | 1 | 1 | 26 |00:03:24.11 |* 21 | INDEX UNIQUE SCAN | AD_PERDET_ID_PK | 43983 | 1 | 43983 |00:00:00.78 | 9 | NESTED LOOPS | | 1 | 1 | 43983 |00:02:29.76 |* 10 | HASH JOIN RIGHT ANTI | | 1 | 1 | 6762K|00:00:35."ID_PORTFOLIO_ADDRESS") filter((UPPER("B".access("A".14 | 8 | NESTED LOOPS | | 1 | 1 | 43983 |00:02:35."ID_SERVICEPOINT"="ID_SERVICEPOINT") 12 .A „Simple‟ Example Of Bad Cardinality Estimate Trouble Shooting ---------------------------------------------------------------------------------------------------| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time ---------------------------------------------------------------------------------------------------|* 1 | VIEW | | 1 | 1 | 26 |00:03:24.18 |* 17 | INDEX UNIQUE SCAN | AD_PORTADD_PK | 6762K| 1 | 43983 |00:02:32.30 |* 20 | INDEX UNIQUE SCAN | SD_CUSTTYPE_ID_PK | 43983 | 1 | 43983 |00:00:00.01 | 16 | TABLE ACCESS FULL | AD_SERVICE_POINT | 1 | 6762K| 6762K|00:00:14."INCOMP_POSTCODE"))) 18 ."ID_PORTFOLIO_ADDRESS"="B"."ID") 21 .50 | 19 | TABLE ACCESS BY INDEX ROWID | SD_CUSTOMER_TYPE | 43983 | 1 | 43983 |00:00:00."OUT_POST_CODE")='FY1' AND INTERNAL_FUNCTION("B".filter(("SD_JOB_STATUS"=10003 OR "SD_JOB_STATUS"=10011)) 13 .access("C"."ID_PERSONAL_DETAILS") | Buffers | Reads | | | | | | | | | | | | | | | | | | | | | 13M| 13M| 13M| 13M| 13M| 13M| 13M| 13M| 13M| 91941 | 409 | 409 | 34 | 91532 | 700 | 9083 13M| 87968 2 | | W 637 | 637 | 637 | 148K| 148K| 148K| 148K| 148K| 147K| 147K| 147K| 131K| 91844 | 376 | 37 637 0 0 0 0 | | | | 0 | 91468 | 59 .access(("SD_JOB_TYPE"=10002 OR "SD_JOB_TYPE"=10003)) 14 ."SD_CUSTOMER_TYPE"="F".06 |* 12 | TABLE ACCESS BY INDEX ROWID| TR_JOB | 2 | 8237 | 3 |00:00:00.35 | 15 | TABLE ACCESS FULL | AD_BEST_ADDRESS | 1 | 102K| 102K|00:00:00.00 | |* 4 | SORT ORDER BY STOPKEY | | 1 | 1 | 26 |00:03:24.01 |* 14 | HASH JOIN RIGHT OUTER | | 1 | 6762K| 6762K|00:00:28.access("A".66 | 7 | NESTED LOOPS | | 1 | 1 | 43983 |00:02:36."ID_BEST_ADDRESS") 17 .86 | 6 | NESTED LOOPS | | 1 | 1 | 43983 |00:02:36.filter(ROWNUM<=26) PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------------------------10 .

In cases where queries may take hours to run. running statements with the GATHER_PLAN_STATISTICS hint may not be practical without taking the query apart. 60 . We will use a divide and conquer strategy to work out where the predicted cardinality is going wrong.A More Complex Example    Lets turn the complexity setting up a notch.

74 | 2 | SORT UNIQUE | | 1 | 27 | 52 |00:01:33.52 |* 18 | TABLE ACCESS BY INDEX ROWID | AD_BEST_ADDRESS | 107 | 1 | 107 |00:00:00.54 |* 12 | TABLE ACCESS BY INDEX ROWID| AD_SERVICE_POINT | 1 | 1 | 107 |00:00:00.93 | 9 | NESTED LOOPS | | 1 | 1 | 107 |00:00:02.0 |* 16 | INDEX UNIQUE SCAN | SD_FIELDREG_ID_PK | 107 | 1 | 107 |00:00:00.55 | 11 | NESTED LOOPS | | 1 | 1 | 107 |00:00:01. .62 | 26 | TABLE ACCESS FULL | AD_WALKROUTE | 1 | 10061 | 10061 |00:00:00.85 |* 29 | TABLE ACCESS FULL | AD_SERVICE_POINT | 1 | 5945 | 2043K|00:00:16. |* 31 | INDEX FAST FULL SCAN | AD_PORTADD_PK | 1 | 67137 | 6668K|00:00:06.28 | 14 | TABLE ACCESS BY INDEX ROWID| AD_WALKROUTE | 107 | 1 | 107 |00:00:00.37 | 30 | INDEX FAST FULL SCAN | AD_CUSTOMER_IX1 | 1 | 6296K| 6296K|00:00:00.63 |* 23 | SORT UNIQUE STOPKEY | | 1 | 5945 | 26 |00:01:31.63 |* 21 | COUNT STOPKEY | | 1 | | 26 |00:01:31.04 |* 15 | INDEX UNIQUE SCAN | AD_WALKROUTE_PK | 107 | 1 | 107 |00:00:00.11 |* 5 | COUNT STOPKEY | | 1 | | 26 |00:00:02. .A „Complex‟ Example Of Bad Cardinality Estimate Trouble Shooting I said I would provide a more involved example of plan for working through bad cardinality estimate trouble shooting .63 | 24 | NESTED LOOPS | | 1 | 5945 | 1799K|00:01:30. .01 |* 17 | INDEX UNIQUE SCAN | AD_CUST_ID_PK | 107 | 1 | 107 |00:00:00.99 |* 28 | HASH JOIN | | 1 | 5945 | 1800K|00:00:34.01 |* 20 | VIEW | | 1 | 26 | 26 |00:01:31. |* 13 | INDEX FULL SCAN | AD_SERVICE_POINT_IX6 | 1 | 1 | 1109 |00:00:00.01 |* 27 | HASH JOIN | | 1 | 5945 | 1799K|00:01:20.11 | 8 | NESTED LOOPS | | 1 | 1 | 107 |00:00:02.11 |* 7 | SORT UNIQUE STOPKEY | | 1 | 1 | 26 |00:00:02.20 ---------------------------------------------------------------------------------------------------| Buffers | Reads | | | | | | | | | | | 199K| 199K| 199K| 4301 | 4301 | 4301 | 4301 4290 | 3967 | 3751 | 3749 | 304K| 304K| 304K| 3703 | 3703 | 3703 | 3692 | 3674 | 3547 3546 62937 62937 0 | 0 0 | | | | | | | | | | | 195K| 195K| 195K| 195 159K| 159K| 159K| 102K| 300K| 300K| 300K| 300K| 300K| 300K| 137K| 629 6 6 6 | continued .74 | 3 | UNION-ALL | | 1 | | 52 |00:00:02.11 |* 4 | VIEW | | 1 | 1 | 26 |00:00:02. |* 19 | INDEX UNIQUE SCAN | AD_BESTADD_PK | 107 | 1 | 107 |00:00:00.02 |* 25 | HASH JOIN | | 1 | 5945 | 1799K|00:01:24.63 | 22 | VIEW | | 1 | 5945 | 26 |00:01:31.6 |* 32 | INDEX UNIQUE SCAN | SD_FIELDREG_ID_PK | 1799K| 1 | 1799K|00:00:03.14 | 10 | NESTED LOOPS | | 1 | 1 | 107 |00:00:01.11 | 6 | VIEW | | 1 | 1 | 26 |00:00:02. :---------------------------------------------------------------------------------------------------| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time ---------------------------------------------------------------------------------------------------| 1 | VIEW | | 1 | 27 | 52 |00:01:33. 61 . .

"ID_BEST_ADDRESS") 20 ."ID_BEST_ADDRESS" IS NOT NULL) 15 ."SD_FIELD_REGION"="ID") 17 ."INCOMP_POSTCODE")='N') 32 .access("A"."SD_SERVICEPOINT_STATUS")))) 31 ."SD_SERVICEPOINT_STATUS"=10001 AND "A"."SD_SERVICE_TY 13 .filter(ROWNUM<=26) 23 .filter(UPPER("B"."ID_WALKROUTE" IS NOT NULL AND UPPER("A"."ID_WALKROUTE"="C"."ID_PORTFOLIO_ADDRESS"="B".A „Complex‟ Example Of Bad Cardinality Estimate Trouble Shooting Predicate Information (identified by operation id): --------------------------------------------------4 5 7 12 filter("RNUM">0) filter(ROWNUM<=26) filter(ROWNUM<=26) filter(("A"."SD_OCCUPIED_ INTERNAL_FUNCTION("A".filter(ROWNUM<=26) 25 ."ID_CUSTOMER"="D"."ID_CUSTOMER") 29 .access("C"."SD_SERVICE_TYPE"=10000) OR ("A".filter("RNUM">0) 21 ."ID_CUSTOMER") 18 .filter(("A"."SD_SERVICEPOINT_STATUS"=10001 AND "A"."ID_WALKROUTE") 16 ."ID_CUSTOMER"="D"."ID_PORTFOLIO_ADDRESS") 28 ."ID_WALKROUTE"="C".access("A".cpu costing is off (consider enabling it) PLAN_TABLE_OUTPUT 62 .filter("A".access("C"."ID_BEST_ADDRESS" IS NULL AND UPPER("A".access("A"."WALKROUTE_REVIEWED_FLAG")='Y' AND (("A" PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------------------------("A"."INCOMP_POSTCODE")='N') 19 ."SD_FIELD_REGION"="ID") Note ----.filter(UPPER("B"."ID_WALKROUTE") PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------------------------27 ."ID_WALKROUTE" IS NOT NULL AND "A".access("A".access("A"."WALKR AND "A"."SD_OCCUPIED_STATUS"=10001 AND "A".access("A"."ID_BEST_ADDRESS"="B".

Oracle thinks that the predicates associated with line 28 are for line 29.filter(("A".000."SD_SERVICEPOINT_STATUS"=10001 AND "A". 63 . this means that there are predicates associated with this table."SD_OCCUPIED_ INTERNAL_FUNCTION("A". lets look at these 29 ."SD_SERVICE_TYPE"=10000) OR ("A".800.85 | 102K| 137K| |* 28 |  We have an estimated cardinality of 5945 versus an actual cardinality of 1. This is line 28 in our plan:HASH JOIN | | 1 | 5945 | 1800K|00:00:34."SD_SERVICEPOINT_STATUS"))))   Due to a possible bug."WALKR AND "A". Now lets use a “Divide and conquer” strategy for working out where exactly in this list of predicates that are OR-ed and AND-ed together the estimate is going wrong. Notice the „*‟ at the beginning of the line."ID_WALKROUTE" IS NOT NULL AND "A"."ID_BEST_ADDRESS" IS NULL AND UPPER("A".A „Complex‟ Example Of Bad Cardinality Estimate Trouble Shooting    Start by looking for the row source which is the furthest into the execution plan for where the cardinality is out by an order of magnitude.

.sd_servicepoint_status = '10000' OR a.display_cursor(NULL. child number 0 ------------------------------------SELECT /*+ GATHER_PLAN_STATISTICS */ COUNT(*) FROM ad_service_point a WHERE a.Trouble Shooting – 1st Pass 1 SELECT /*+ GATHER_PLAN_STATISTICS */ COUNT(*) ad_service_point a a.sd_service_type = '10001' AND a.'ALLSTATS LAST')).walkroute_reviewed_flag) = 'Y' AND ( ( a. .sd_servicepoint_status = '10001' ) OR ( a.id_best_address IS NULL UPPER (a.sd_service_type = '10000' AND a. PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------------------------SQL_ID 9qvfwxgnv1scj.sd_servicepoint_status = '10003' ) 2 3 FROM 4 WHERE 5 AND 6 AND 7 8 9 10 11 12 13* 14 / COUNT(*) ---------2043175 SQL> select * from table(dbms_xplan.NULL.sd_servicepoint_status = '10003' ) Plan hash value: 185642247 PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | ---------------------------------------------------------------------------------------------------| 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:17.sd_occupied_status = '10001' AND a.42 | 92450 | 9 ---------------------------------------------------------------------------------------------------.77 | 92450 | 92426 | |* 2 | TABLE ACCESS FULL| AD_SERVICE_POINT | 1 | 19524 | 2043K|00:00:18.sd_servicepoint_status = '10000' OR a. 64 .sd_service_type = '10000' AND a.sd_servicepoint_status = '10001' ) OR a.sd_service_type = '10001' AND a.id_best_address IS NULL AND UPPER (a. .sd_servicepoint_status = '10001' ) OR ( a.walkroute_reviewed_flag) = 'Y' ( ( a.sd_servicepoint_status = '10001' ) OR a.sd_occupied_status = '10001' AND a.

sd_service_type = '10001' AND a.id_best_address IS NULL UPPER (a.sd_servicepoint_status = '10001' ) OR ( a. 65 .sd_servicepoint_status = '10001' ) OR a.sd_service_type = '10000' AND a.sd_occupied_status = '10001' AND a.sd_servicepoint_status = '10003' ) 2 3 FROM 4 WHERE 5 AND 6 AND 7 8 9 10 11 12 13* 14 /  For our second pass lets work which one of these sections is causing the cardinality estimate to go wrong.Analysis Of 1st Pass  We have two sets of predicates the id_best_address IS NULL and UPPER(a.sd_servicepoint_status = '10000' OR a.walkroute_reviewed_flag) = 'Y' ( ( a. 1 SELECT /*+ GATHER_PLAN_STATISTICS */ COUNT(*) ad_service_point a a.walkroute_reviewed_flag) = „Y‟ and a load of stuff relating to standing data columns within brackets.

66 .id_best_address IS NULL UPPER (a. 1 SELECT /*+ GATHER_PLAN_STATISTICS */ COUNT(*) ad_service_point a a.sd_servicepoint_status = '10000' OR a.sd_service_type = '10001' AND a.sd_service_type = '10000' AND a.sd_servicepoint_status = '10003' ) 2 3 FROM 4 WHERE 5 AND 6 AND 7 8 9 10 11 12 13* 14 /  For our second pass lets work which one of these sections is causing the cardinality estimate to go wrong.walkroute_reviewed_flag) = 'Y' ( ( a.sd_occupied_status = '10001' AND a.sd_servicepoint_status = '10001' ) OR a.sd_servicepoint_status = '10001' ) OR ( a.Analysis Of 1st Pass  We have two sets of predicates the id_best_address IS NULL and UPPER(a.walkroute_reviewed_flag) = „Y‟ and a load of stuff relating to standing data columns within brackets.

display_cursor(NULL.37 | 92450 | 92426 | PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------------------------|* 2 | TABLE ACCESS FULL| AD_SERVICE_POINT | 1 | 6712K| 6712K|00:00:13.'ALLSTATS LAST')). PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------------------------SQL_ID 2545fjyq0m5nm.NULL.46 | 92450 | 9 ---------------------------------------------------------------------------------------------------Predicate Information (identified by operation id): --------------------------------------------------2 . child number 0 ------------------------------------SELECT /*+ GATHER_PLAN_STATISTICS */ COUNT(*) FROM ad_service_point a WHERE a.'ALLSTATS LAST')) /*+ GATHER_PLAN_STATISTICS */ COUNT(*) ad_service_point a a."ID_BEST_ADDRESS" IS NULL) Note ----. 1* select * from table(dbms_xplan.Trouble Shooting .display_cursor(NULL.id_best_address IS NULL SQL> SELECT 2 3 FROM 4 WHERE 5 / COUNT(*) ---------6712561 SQL> select * from table(dbms_xplan.cpu costing is off (consider enabling it) 67 .NULL.filter("A".2nd Pass  It appears that the cardinality estimate is going wrong in the section in brackets.id_best_address IS NULL Plan hash value: 185642247 ---------------------------------------------------------------------------------------------------| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | ---------------------------------------------------------------------------------------------------| 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:16.

display_cursor(NULL.03 | 6 | ---------------------------------------------------------------------------------------------------Predicate Information (identified by operation id): --------------------------------------------------3 .sd_servicepoint_status = '10000' a. child number 0 ------------------------------------SELECT /*+ GATHER_PLAN_STATISTICS */ COUNT(*) FROM ad_service_point a WHERE a. PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------------------------SQL_ID 4rjg28wg48zv7.sd_servicepoint_status = '10003' Plan hash value: 2502039880 ---------------------------------------------------------------------------------------------------| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | ---------------------------------------------------------------------------------------------------| 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.Trouble Shooting – 3rd Pass  1 Lets break down the section in brackets. SELECT /*+ GATHER_PLAN_STATISTICS */ COUNT(*) ad_service_point a a.'ALLSTATS LAST')).sd_servicepoint_status = '10000' OR a."SD_SERVICEPOINT_STATUS"=10003)) 5 | 5 | Note ----- 68 ."SD_SERVICEPOINT_STATUS"=10000 OR "A".access(("A".03 | 6 | 5 | PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------------------------| 2 | INLIST ITERATOR | | 1 | | 282 |00:00:00.NULL.02 | 6 | |* 3 | INDEX RANGE SCAN| AD_SERVICE_POINT_IX5 | 2 | 282 | 282 |00:00:00.sd_servicepoint_status = '10003' 2 3 FROM 4 WHERE 5* OR SQL> / COUNT(*) ---------282 SQL> select * from table(dbms_xplan.

'ALLSTATS LAST')). child number 0 ------------------------------------SELECT /*+ GATHER_PLAN_STATISTICS */ COUNT(*) FROM ad_service_point a WHERE a.sd_servicepoint_status = '10003' Plan hash value: 2502039880 ---------------------------------------------------------------------------------------------------| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | ---------------------------------------------------------------------------------------------------| 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.sd_servicepoint_status = '10000' a. SELECT /*+ GATHER_PLAN_STATISTICS */ COUNT(*) ad_service_point a a.access(("A"."SD_SERVICEPOINT_STATUS"=10003)) 5 | 5 | Note ----- 69 .sd_servicepoint_status = '10003' 2 3 FROM 4 WHERE 5* OR SQL> / COUNT(*) ---------282 SQL> select * from table(dbms_xplan.Trouble Shooting – 4th Pass  1 Lets break down the section in brackets.02 | 6 | |* 3 | INDEX RANGE SCAN| AD_SERVICE_POINT_IX5 | 2 | 282 | 282 |00:00:00.NULL.display_cursor(NULL."SD_SERVICEPOINT_STATUS"=10000 OR "A".sd_servicepoint_status = '10000' OR a.03 | 6 | 5 | PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------------------------| 2 | INLIST ITERATOR | | 1 | | 282 |00:00:00. PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------------------------SQL_ID 4rjg28wg48zv7.03 | 6 | ---------------------------------------------------------------------------------------------------Predicate Information (identified by operation id): --------------------------------------------------3 .

"SD_OCCUPIED_STATUS"=10001 AND "A".sd_service_type = '10001' AND a.sd_servicepoint_status = '10001' ) OR ( a. PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------------------------SQL_ID 17vy5ysvdqgxd.sd_service_type AND a.sd_servicepoint_status = = = = = '10000' '10001' ) '10001' '10001' '10001' ) ) | PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:17.sd_occupied_status AND a.'ALLSTATS LAST')).90 | 92450 | 92426 | |* 2 | TABLE ACCESS FULL| AD_SERVICE_POINT | 1 | 1952K| 2070K|00:00:18.sd_occupied_status = '10001' AND a.display_cursor(NULL.Trouble Shooting – 5th Pass 1 SELECT 2 3 FROM 4 WHERE 5 6 7 8* SQL> / COUNT(*) ---------2070646 SQL> select * from table(dbms_xplan.sd_service_type AND a."SD_SERVICE_TYPE"=10000 OR ("A".67 | 92450 | 9 ---------------------------------------------------------------------------------------------------Predicate Information (identified by operation id): --------------------------------------------------2 .sd_service_type = '10000' AND a.sd_servicepoint_status = '10001' ) ) Plan hash value: 185642247 ---------------------------------------------------------------------------------------------------| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads /*+ GATHER_PLAN_STATISTICS */ COUNT(*) ad_service_point a ( ( a.filter(("A". child number 0 ------------------------------------SELECT /*+ GATHER_PLAN_STATISTICS */ COUNT(*) FROM ad_service_point a WHERE ( ( a.NULL."SD_SERVICE_TYPE"=10001)))) 70 .sd_servicepoint_status OR ( a."SD_SERVICEPOINT_STATUS"=10001 AND ("A".

Trouble Shooting – 6th Pass 1 SELECT 2 3 FROM 4 WHERE 5* SQL> / /*+ GATHER_PLAN_STATISTICS */ COUNT(*) ad_service_point a ( ( a.'ALLSTATS LAST')).71 | 18 ---------------------------------------------------------------------------------------------------- 71 .sd_servicepoint_status = '10001' ) ) Plan hash value: 1416185116 ---------------------------------------------------------------------------------------------------| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | ---------------------------------------------------------------------------------------------------| 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:04.sd_servicepoint_status = '10001' ) ) COUNT(*) ---------1679148 SQL> select * from table(dbms_xplan. PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------------------------SQL_ID 2qd1zzbj3qgf7.sd_service_type = '10000' AND a.display_cursor(NULL.NULL.74 | 18921 | 18859 | |* 2 | INDEX FAST FULL SCAN| AD_SERVICE_POINT_IX11 | 1 | 1679K| 1679K|00:00:01.sd_service_type = '10000' AND a. child number 0 ------------------------------------SELECT /*+ GATHER_PLAN_STATISTICS */ COUNT(*) FROM ad_service_point a WHERE ( ( a.

Trouble Shooting – 7th Pass SELECT /*+ GATHER_PLAN_STATISTICS */ 2 COUNT(*) 3 FROM ad_service_point a 4 WHERE ( ( a.sd_service_type = '10001' 5 AND a.display_cursor(NULL.47 | 92450 | 92426 | |* 2 | TABLE ACCESS FULL| AD_SERVICE_POINT | 1 | 364K| 391K|00:00:18.17 | 92450 | 9 ---------------------------------------------------------------------------------------------------1 72 .sd_occupied_status = '10001' AND a.'ALLSTATS LAST')).sd_occupied_status = '10001' 6* AND a.sd_servicepoint_status = '10001' ) ) Plan hash value: 185642247 ---------------------------------------------------------------------------------------------------| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | ---------------------------------------------------------------------------------------------------| 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:16.NULL.sd_servicepoint_status = '10001' ) ) SQL> / COUNT(*) ---------391498 SQL> select * from table(dbms_xplan. child number 0 ------------------------------------SELECT /*+ GATHER_PLAN_STATISTICS */ COUNT(*) FROM ad_service_point a WHERE ( ( a.sd_service_type = '10001' AND a. PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------------------------SQL_ID 186k84m0t9rmx.

sd_occupied_status = '10001' AND a.sd_service_type = '10000' AND a.sd_servicepoint_status = '10001' ) ) 73 .sd_service_type = '10001' AND a.sd_servicepoint_status = '10001' ) ) SELECT /*+ GATHER_PLAN_STATISTICS */ COUNT(*) FROM ad_service_point a WHERE ( ( a.Analysis Of 7th Pass It appears that the cardinality estimate goes awry when Oracle is combining the cardinalities of:1 2 3 4 5 6* and:1 SELECT 2 3 FROM 4 WHERE 5* SQL> / /*+ GATHER_PLAN_STATISTICS */ COUNT(*) ad_service_point a ( ( a.

FLUSH_DATABASE_MONITORING_INFO  Then run:- SELECT num_rows. user_tab_modifications m WHERE t.table_name AND table_name = < your table name > 74 .table_name = m.Analysis Of 7th Pass  To rule out statistics:  We could re-compute statistics on the AD_SERVICE_POINT table. updates. this may ok for a test / development environment but it may not be practical to do this on a production environment on ad-hoc basis. last_analyzed. which it should be by default you flush the monitoring information:- SQL> execute DBMS_STATS. deletes FROM user_tables t. If table monitoring is enabled. inserts.

SUM(updates). last_analyzed / You can see from this that it wouldn‟t be that difficult to produce something similar that works for indexes.Analysis Of 7th Pass  To rule out statistics:  We could re-compute statistics on the AD_SERVICE_POINT table.table_name. which it should be by default you flush the monitoring information:- SQL> execute DBMS_STATS. 75 . user_tab_modifications m WHERE t.table_name AND timestamp > last_analyzed AND t. If table monitoring is enabled. last_analyzed.FLUSH_DATABASE_MONITORING_INFO  Then run:- SELECT t.table_name. SUM(inserts). this may ok for a test / development environment but it may not be practical to do this on a production environment on ad-hoc basis.table_name = m.table_name = <your table name> GROUP BY t. SUM(deletes) FROM user_tables t.

 The exact nature of the problem is that if there are predicates on the same table for which the data in the relevant columns is related. the optimizer always assumes that these are independent. This culminates in:=> incorrect selectivitys  => incorrect cardinality estimates => sub-optimal plans 76 .Analysis Of 7th Pass  This particular issue is down to what:  people from Oracle call “data correlation” and what some people from outside of Oracle coin “the predicate independence assumption”.

” “How many people will raise their hands if I ask for all the people born under Aries and in December to raise their hands? What about all the people born under Aries in March? What about the people born under Aries in April ? According to Oracle the answer will be the same for all three questions:   Selectivity (month AND star sign) = selectivity (month) * selectivity (star sign) = 1/12 * 1/12 = 1 /144 Cardinality = 1.Analysis Of 7th Pass  This issue has been covered in great depth by the Oracle community that focus on the CBO.5 (rounded to 8 or 9 depending on version of Oracle). . . and we assume even distribution of data – selectivity is 1/12. . cardinality is 1.200 * 1/144 = 8. If I ask all the people born under Aries to raise their hands.” 77 . there are 12 star signs. . .200 / 12 = 100. I expect to see 100 hands. .Assume everyone in the audience knows which star sign they were born under . Jonathan Lewis describes this as:“ .

the level of sampling performed depends on the sampling level.  Extended statistics (Oracle 11g onwards) allows you to gather statistics on columns containing related data.  Hints to force the optimizer down the appropriate execution path.  Oracle 11g automatic tuning ?. this causes Oracle to sample the data being queried.  SQL profiles (Oracle 10g onwards).Analysis Of 7th Pass  Solutions to the data correlation / predicate independence assumption issue include: dynamic sampling (9i onwards). Oracle uses what is known as offline optimization to sample data and partially execute the query in order to create a profile containing cardinality scaling information. 78 .

Section 4 Summary & “Wrap Up” 01/05/2012 79 .

your technical knowledge needs to be augmented with good practise and knowledge of common pit falls. To be affective at tuning.Summary    Having good technical knowledge will only get you so far. This will be covered on the remaining slides. 80 .

timings. Remember that timings are ultimately what is important to the business.Tuning Objectives    Set clear and well defined performance goals. 81 . concurrent users. How do you know you have met your goals without targets ?. CPU / IO loading. in terms of data volume.

Do not assume you can use the tuning advisor to solve all your ills because Oracle have mentioned this. be aware of likely causes. Do not use dynamic_sampling all over the place because I have mentioned this. but appreciate that one size does not fit all. Do not pick up text book or article from the internet describing a performance enhancing feature and apply it blindly across an application.Tuning By Magic Bullets       Do not tune using „magic bullets‟. . when faced with a problem. . Etc . !!! ONE SIZE DOES NOT ALWAYS FIT ALL !!! 82 .

uk.co. A piece of SQL performing meaningless work can perform lots of logical reads and hence lead to a good BCHR. Take the buffer cache hit ratio (bchr) for example.oracledba. Refer to custom hit ratio from www. 83 .Tuning By Hit Ratios     Hit ratios can hide a multitude of sins.

can you please demonstrate with an example ? (I will be using PL/SQL for coding) Thanks. what steps/guidelines are to be followed. You Asked If LIOs are bad. 1). If yes. is it possible to reduce the LIOs programatically ? 2). Uday 84 . inorder to reduce/avoid LIOs ? 3). what is a "OK" number of the LIOs (some percentage of SGA or PIO etc ?) If possible. .Hit Ratios According To Tom Kyte The following was posted on Ask Tom 4 December 2002 . . . while coding.

. If you are joining a 1.forget about them.cache hit.000 LIO's -. 96% -. Yet. I have a theory that systems with high cache hit ratios. setting environmental things like sort_area_size or db_file_multi_block_read_count or the optimize_index_* parameters. However. 85 .it is very doubtful that an index should be used. if that query could be executing without doing 1. I have no ratios for you. All other ratios -.then SO BE IT. over 95. Massive nested loop joins are the main culprit of this. There is no magic "good number". 3) ratios STINK ( i have stronger words but this is a public forum after all ).Hit Ratios According To Tom Kyte And we said .000. tuning your SQL.000 rows back -. that is that. It should be near 100 for most systems.000 row table and trying to get 2. .000. It is like the stupidest ratio of them all .000. There is one ratio I use -.soft parse ratio (the ratio of soft to hard parses). my cache hit is 99% so all is well in the world". their DBA's sit there and say "well. If you have a query that you need to execute and the best we can do is 1.000 row table to a 2. 1) by rewriting your SQL. 2) the piece of advice I have for everyone: totally and forever forget the concept that "if my query ain't using an index.000.000 LIO's then we need to fix it. it must be broken".000.are among the most poorly tuned systems. They are Experiencing excessive LIO's due to massive nested loop joins.

jlcomp.co.least (1.uk/hit_ratio. desired response time / actual response time ) ) 86 .pdf 100 * ( 1 .The Fan Hit Ratio  This is a meaningful hit ratio that I first came across in a Jonathan Lewis presentation http://www.demon.

7 comes out.com/2008/03/oraclesupport-keeps-closing-my-tar. .html.1.0. 11g will be no exception. When 11.blogspot. Every Oracle release has bugs and flaws. every feature has it‟s quirks and boundary cases under which things can break.Tuning By Oracle Marketing      Oracle 11g is self tuning => tuning is dead !!! So why has Oracle produced an SQL test case packager in 11g => http://optimizermagic. . New optimizer features are constantly introduced. . 87 . digest and the list of bugs fixed in the optimizer .

88 . e. Prefer web sites and „experts‟ that provide worked examples.Tuning By The Internet   Some organisations publish on the internet are more interested in dominating search engine searches and advertising their books than disseminating advice grounded on well documented test cases and evidence. Tom Kyte and Jonathan Lewis.g.

there are DBAs out there who when faced with a performance issue will look at adjusting obscure parameters which most DBAs in their professional careers will never have any need to touch. For example. 89 . Yes.Tuning By “Problem Scope”    The scope of a solution to a performance problem should match the scope of the problem. histogram than a system wide parameter change. an issue is caused by one particular SQL statement is more likely to be resolved by something such as a new index. index change.

how it behaves under load. pick the bottle necks off one by one. Understand the “flight envelope” of you application. 90 . Do not blindly pick an Oracle feature conducive to good performance.Tuning What You Know     Always tune what you know. find where the time is going to first and then apply tuning techniques accordingly. Refer to Cary Milsap‟s presentation on performance and skew from Oracle Open World 2008.

Tuning Is A Moving Target  The RDBMS is constantly evolving. in 11g release 1 alone we have:Extended statistics  Null aware joins  Adaptive cursors  Plan base lining  A new method of calculating density   Protect yourself from this by thorough testing 91 .

therefore that must be my problem”. parsing etc Wait time = waiting on an event I/O. contention etc Understand this basic equation and its context with your application.Understand Response Time      Response time = wait time + service time Service time = CPU time => joining. 92 . Avoid blind scatter gun techniques such as looking at your software with a monitoring tool and saying “hey there is a lot of latching taking place. work off the top waits events and drill down.

it is doing 3000 Rpm at 60 Mph. you say there is a performance issue with the engine. The mechanic will probably ask:When did first start happening  Under what driving conditions does this happen  Does this happen consistently  Have there been any changes to your car. when was it last serviced.Tuning Via Flat Statistics   You get a mechanic to look at your car.  93 .

Tuning Via Flat Statistics

The moral of this story is that a single statistic in isolation is not that useful. In order to put statistics into context you need to also understand things such as:where is most of the time going in your application ?  What is the normal performance base line or “Flight envelope” for your application  Is you think you are seeing strange and anomalous behaviour, what conditions does it occur under ?

94

Know Your Tool Kit

   

Performance views 10g tuning infra structure, ASH, advisors, ADDM and the time model. SQL trace, SQL extended trace, tkprof, trcsess. O/s tools, iostat, sar etc . . . DBMS_XPLAN Your tuning arsenal should consist of more than explain plan and the ability to spot full table scans.
95

Understand Key Object Statistics

 


 

Histograms, frequency and height balanced, MetaLink note 72539.1. Index quality => clustering factors, many DBAs do not understand this, this gets a whole chapter in Jonathan Lewis‟s Cost Based Fundamentals book. MetaLink notes 39836.1 and 223117.1 Predicate selectivity, MetaLink note 68992.1 System statistics aux_stats$, MetaLink note 153761.1 Sample sizes Numbers of distinct values. Etc . . .
96

centrexcc.com/ The Oracle Optimizer Group Blog http://optimizermagic. look out for those in particular from Chritian Antognini http://www.com/SearchIntelligenceCBO.com/en/know-how-community/download-area.com General Oracle papers.com/ Wolfgang Breitling‟s web site (a reviewer of Jonathan Lewis‟s CBO book) www.evdbt.blogspot.org Jonathan Lewis‟s blog http://jonathanlewis.trivadis.Useful Internet Resources       The Oracle Real World performance group blog http:/www.structureddata.wordpress.html “The Search For Intelligent Life In The Cost-Based Optimizer” by Anjo Kolk: http://www.doc 97 .

7/3.9./5.7484:7..2470.908 -47/078412.91473090..798 #48 #48 490780  #48 #48 &8:.147..-...0.3/ 0.908/1107174290570/./0/  .3/ #48.90/..90/.9.3!70/.7/3..4:2382.0 3903098/0.8.908 %00.0/ 130890/445438.7/3.4:88/0.:9435.90/.3 7550 974:4:990708941905./0/ 3039000.90/ '078:8892.2509.39:/0 983.3900892.38.0 4909..250-0574..3-0574.70:80/ 89.3.8908250890.3./9454475071472.2504390570.42500.98343.:7.:08390 #48.

989.3-070.908033.90/ .:948.4770.3324709.253.3..8.3574/:.989.9438 4:2389800/.#0.9 .7/3..843847892.9 0892..3/893.910/990$*$%%$! $*$%%$3 .9.90 $9..439.:7...:0803.089.907329.90841/893.:08..

943 4790 570/..90/ .70:80/  .305070 495488-0:3994.8431:3.2..4770..4:238 988/:094.4770.88:25943 2470 4398.0.0/ /.989.9438:3088 1:3.943-.25347398.9884209208.90789. .843.989.8.2538 :80/ 495488-0:3994.907 3 /3.903/0503/03.9.80/3/008.90789.8.

.28994410-:.8.25080 3 .08 89.. /...2.9. $.8390/.305070 .418947.9.989.843847892.089.7 ..8  ..4:78041574.8 $9.4:2389800//.253.989.0 :7390.250/89.9934 43077010.:..7.90/ . /3.79.989.943.7/3.989./.989.9.989089.:7..9.9..3088:.8.90 430705708039.9.8.7 574-029 8.03994482.0883/.:7.89.908033.9..7028834789.253.9089.989.28478947.#0..:948.09843 .5.

78438.70/1107039949480:80/-90.389  .843847892.:08390#.70-032.#0.9.:7./0.90 59207:31703/$" &83.4:238 ..7/3....:8089/..425..90/ .908033.9508 .

908033.90/ .90 9071.:7..7/3..#0..9478 59207-:8  .843847892.

308 905.7/3.3 39017895.0/.890/.7.9:83 /3..3982.0147..193.4:914790:80 411:3.01789 995.041 098.3/057088438 14:7:339490 !70/.9884:/-0.3.903/0503/03.7/3..88:25943  88:0988..0890459207..80. 44.253 70.3 4:..94:3:994.9.344307-090 -089 5.9./98.3..9 790$"9.79..2.9892.04:789.9438.07 .9.-.88443.9  0 .4713014790/.34:7/./.9.990920 4190893 40.4770.0.*8.908.90892..908 3982.4770.9.

.

9:70//.9. 47.897:.

 .

.

.

2.253. 8.9070 8 34 920 0 34 94 :80 /3.

&80398.0801.3/57410803.8  .

93:2-0741-:.3.908 8947.2884:/-05708039147.098 3.9...89708479  .9413.4:2389 800//.7/ 5.4770..70706:70/  90..9892.9398.3.8.94343/.29439403/54398894708 3431472..70.0885.70.990.783974:-3/5003 8947.908947.80/.2807090.398147*$!43:80 ./.0908/0.9.110./897-:943 &3088.7/3.

$0.900/-.7/3..943 470/. .2508 1%:33 .

.

   .

89*1.8 .709*70.//7088*30  ./*507843.425*5489./*5479144*.4/0  . . - .05439*701/ .//7088*30$-089*. # &73:2 #  $%$%%.20 .//7088*30  - .4/0 $4:9*3*5489.4/0   ##4:9*3*5489.//7088*30  .75943 .8 .  %- 4:9*5489*..74:90701/ .9:8     8/*4-*950     &!!# - 4:9*5489*.//7088*30  .4/0  - 3*5489*.*/09.//7088*30$-089*. /*.425*5489.//7088*30  .20 - 4:9*5489*.05439  # &%# $.//7088*30 - . 8/*.//7088*30 - . /*507843.//7088*30 - .//7088 /*-089*.4/0   3*5489*.7/3. .250 1./*. ## & #73:2  . 9.0*5439.//7088*30$-089*.//7088 . 8/*.*/09.//7088*30 - .4/0 .20  / 8:73.:894207.90%74:-0$4493 $% #  $%./*/.:894207 .9 892./..20 / 14703. /*807.4/0  3*5489*.4/0 $ 4:9*5489*.//7088.//7088 #.05439 % $%/*807.4/0 - 3.*/09.//7088*30 - .//7088*30$-089*. .:894207 1 $.//7088*30 - ./*-089*. /*5479144*.//7088*30$-089*./3*3.:894207*9501  - 3.//7088*30  ./*807. /*807.//7088 . /4*349*.4/0 # .//7088*30  - . /*.//7088*30  .4/0$-089*4:9*5489*.//7088*1.//7088*1.//7088- /*5479144*.//7088*30$-089*.//7088*30  .//7088*30$-089*.//7088*30 $-089*.//7088*30  .4/0 3   . $250 .. 807.//7088*30  . /*-089*.8/ 8/*. .//7088*30 - .//7088*30  .4/0$-089*3*5489*. /*.4/0 - -09907*.//7088*30   4:9*5489*.//7088*30 1 /08.//7088*30$-089*.//7088*30 - .//7088*30$-089*.//7088*30  .//7088*30$-089*.20 / 2//03.:894207*950 .:894207*9501 . -:83088*3. 97.//7088*30 - .:894207.:894207*701 ..90 .4/0  - 3*5489*..:894207/ $- -09907*.//7088*30$-089*.*/09.8/ /*507843. /*507843.05439 # 97*4#8/*4-*89..

.088  *$%*#$$ *$%*#$$  1907 %#*&%  $* *$%%&$ %#*&%  $* *%!  ..90%74:-0$4493 / 507.088  *$#'! %*$#'! % !*%* &%!&%  ....088  *! #%  *#$$ *! #%  *#$$  1907 &!!#   &%*! $%*    %#*&%    !*! $%   .20$9.943.088  $*&$% #*%!    .798 #48 #48 %20:11078#0..088  *!#$ *%$ *!#$ *%$  .088  *&$% # *&$% #  ./879  '         &%$% !       '        $ #% ##$% !      $&"&     $% !$     $% !$     $% !$       $ %        $% !$ &%#       $         $%&$*! #%*!    %$$&*$#'*! %      %$$# *$%*#$$     &"&$*$%*!     $%&$%#* *      &"&$*&$%**!     %$$# $*&$% #*%!     &"&$$*&$%%!**!      &"&$*!#%**!    !70/...7/3...943/   1907 #&  1907 # &  1907 # &  .943 /03910/-4507. $250 ...9031472.9 892.250 1./..

4:23*3.4:23*3.4:23*3.7/3.4:39 1742:807*9.990/893.9.9908947.3/ 8/*4-*89. $250 .98/*4-*89.4:39 /893.90.28439080.9.4:238 $"800.9:8 174297*4-  &% $%%$* *%!  &% $%%$* *$%%&$  409844.20 $".2438/*4-*950 09844.4:39 /893.9 892.90%74:-0$4493 098.9.28070.203 $* *%!  $* *$%%&$  74:5-.8947.-*8947.70.20 .4:238 800.250 1./.98/*4-*950 ..:083908/*4-*950.9:8.

 &* &% $* *$%%&$ $* *%!  .

250 1.90/ .98 ./-28*89.908.93043905.90/.3/.573.9433041905.7/3.9843-.3 $"00.70/5449 $*$%%$ 4:8009.3/0990 0892..50419:33-98.39.5574./.90/.907*9.  .70/544 707:3906:07.7/3.-0*89.90*507.9:...039&  2094/*459  # &$ 0 1:8908.4807 034300/9444.908900307../743433041 905..7/3. $250 .7/3..3 -:998 :897.70.9900892.98 :807 %#*  $* *%!$ 0892..9:.90%74:-0$4493 %00892.9 892.9081742908.3/..

..943...7/3..943 /03910/-4507./8  '       &%$% !    '      $ #% ##$% !    $&"&    $% !$    $% !$    $% !$    $% !$      $ #%%     $%%#% #       %$$# %#*       #$%#* *      $ #% &%#     %$$&*$%*#$$       %$$&*$#'*! %      &"&$*! #%*!     &"&$*&$%**!      %$$# $*&$% #*%!       &"&$$*&$%%!**!     &"&$*!#%**!     !70/..9 892.798 #48 #48 %20:11078#0../.088  $*&$% #*%!   .20$9...9031472.088  *$%*#$$ *$%*#$$  .250 1...088 $* *%!  #$* *%!   ..90%74:-0$4493 / 507.088  *$#'! %*$#'! %  1907 $* *$%%&$  #$* *$%%&$   .088  *! #%  *#$$ *! #%  *#$$ 1907 &!!#   &%*! $%*    %#*&%    !*! $%   ..088  *!#$ *%$ *!#$ *%$           .943/   1907 #&  1907 # &  1907 # & !*%* &%!&%   .088  *&$% # *&$% #   ... $250 .

349-0 57.9843743 3.3/.8080706:07082.9020398990 %#*!*$%%$%$392./0.9.94:99..9..90/.4704250.7/3.3906:07.04:78947:3  7:33389./.250 0989:7390. 0:80.349.79  .909447 4:907090570/.4250980993:5...436:07897.5.

3147473974:-.20$9.90892./4:/574.250415.4393:0/    .90974:-084493    / 507.7/3..90%74:-0$4493 8.250 1./ .24703.4. 4250 .798 #48 #48 %20:11078#0.0/0.7/3.943./0.9892./ ./8 '     $ #%&"&     &         '           &%$% !         '          $ #%&"&$% !      $% !$        $% !$        $% !$      $% !$       %$$# *$#'*! %     &$*$#'*! %*     %$$# *# &%       &"&$*# &%*!      &"&$$*#**!       &"&$*&$%**!       %$$# *$%*#$$      &"&$*$%*!        '       &%$% !     '      $ #%&"&$% !    $% !$      $      %$$&*# &%       $       $        %$$&*$#'*! %      $%&$*&$% #*    $%&$*! #%*!      &"&$$*#**!      .

./ ..5:.943/      1907 #& 1907 # & 1907 # & 1907  *# &%$ %&&!!#  # &%*#'*     !*%* &%!&%  $*$#'! %*$%%&$  $* &!*$%%&$  $*$#'*%  1907  *$%*#$$$ %&  .088  *&$% # *&$% #  1907  *# &%$ %& *$%*#$$$&&!!#  #  $*$#'*%!  #  $*$#'! %*$%%&$  $* &!* %#*&%   $*$#'! %*$%%&$  1907 &!!#   !*! $%     ...438/0703.088  $**#   .088  *&$% # *&$% #  1907 &!!#   !*! $%     ..088  *# &% *# &% !*%* &%!&%  ..9031472..48938411 .088  *# &% *# &%  ...088  *$%*#$$ *$%*#$$   1907 #&  1907 # &  1907 # &  ...088  $**#  490 ..943 /03910/-4507.9892.088  *! #%  *#$$ *! #%  *#$$  .... 4250 .250 1.-39 !*%* &%!&%  .7/3...90%74:-0$4493 !70/.

9.347/07412.09389..7/3..8901:7908939490 00.3  $       0.30892. 4250 .436:07 897.7014730 4098:80.9089.990-0333419030 9820.389.:9435..078:8..7/3.0.79-443147907484:7./ .90/.908.884.3/..908.901474734:9070 0.9892.90/9 30..99080  1907  *# &%$ %& *$%*#$$$&&!!#  #  $*$#'*%!  #  $*$#'! %*$%%&$  $* &!* %#*&%   $*$#'! %*$%%&$ :094.250 1.3.884.70 # 0/.90%74:-0$4493 $9.941   49..090 .941.3/ 0/94090790 0892.990570/.99070..7/3.39:/0 %883034:75../0.93988941570/.9:..-0 09844.90843743  .90/9989..0.7/3. .70 570/..984:9-.5488-0-:  7.314707090..

%74:-0$4493 89 !.88 $%.

%#*!*$%%$%$ .

#.05439*89... 8/*807.0*950   .9:8   #. /*-089*... 8/*807.:50/*89.     .  &% # .05439*89.9:8     . 8/*807. 8/*807.05439*89../*807.//7088$& &!!# .9:8    .74:90*70. 8/*807.9:8     # ..0*5439.05439*89.9:8     #.. 8/*4. .00/*1.. 8/*807.0*950  .

 .13.:7847 & & $%%$$%  !*%* &%!&% $"*6.8./3:2-07 $%.9 17429.*.3 /85.  &%   $"800.-0 /-28*5.

%#*!*$%%$%$ .

798 #48 #48 %20:11078#0.00/*1./8 $ #%#%      %$$&*$#'*! %          .05439*89.//7088$&&!!# .8..74:90*70.9:8  #..9:8    !.:50/*89.05439*89.05439*89./*807.9:8    # .. 8/*807. 8/*4.     . 8/*807.# . /*-089*. 8/*807..0*5439..0*950  ..9:8     #.943.0*950   .05439*89. 8/*807. .. 8/*807.9:8   .20$9.:0 !*%* &%!&% / 507. 8/*807...3. &% # .

.00/*1.9394 89.88 0.098 $%.   ..90890/*-089*.3/ &!!# .094809841570/. .4..74:90*70.4:23893-7.//7088$&./4189:1170.88 189 !.3/3/.3.3/.9..

%#*!*$%%$%$ .

. #..9:8     # .00/*1. /*-089*.:50/*89..05439*89.. 8/*807.0*950  ./*807.9:8     #.74:90*70.9:8    .05439*89.0*950   . 8/*807.  &% # .9:8     . .     . 8/*4..9:8   #. 8/*807.0*5439..05439*89. 8/*807.//7088$& &!!# . 8/*807. 8/*807.05439*89...

43/5.90892..:83 90.7/3. 474:780.90944743  ..43041908080.94388.8809847.

88 0.3/3/.4:23893-7.3/ &!!# .9394 89.90890/*-089*.3/.//7088$&.   .. .3.9...4.74:90*70.88 189 !.00/*1./4189:1170.098 $%..094809841570/.

%#*!*$%%$%$ .

05439*89..0*5439./*807.0*950   .9:8     .9:8    .00/*1..9:8   #..74:90*70. 8/*807.. 8/*807.05439*89.:50/*89.. /*-089*.05439*89.//7088$& &!!# .  &% # .     ..0*950  . 8/*807. 8/*807.05439*89. #. . 8/*4..9:8     # .9:8     #. 8/*807.. 8/*807.

43/5.8809847.90944743  .43041908080.:83 90.7/3.. 474:780.94388..90892.

88 9.990..%74:-0$4493 3/ !.*.:7847 & & $"$%.9 17429.-0 /-28*5.550.098  800.9433-7.9084374339080.3 /85.7/3..90892.789.

%#*!*$%%$%$ .

 &% # .//7088$& .. #. /*-089*./*807.0*5439.

 &%  $"800.-0 /-28*5.3 /85.:7847 & & $%%$$%  $%%$$% !*%* &%!&% $"*16 232 .*.9 17429./3:2-07 $%.

%#*!*$%%$%$ .

943 /03910/-4507.5:.:0 / 507.20$9.798 #48 #48 %20:11078#0..//7088$& !./8 $ #%#%     !*%* &%!&%  %$$&*$#'*! %     !70/.9031472.8.943/   1907  *$%*#$$$& 490 .438/0703.943.48938411 . &% # .-39  .3.# ..0*5439./*807.. /*-089*.

.098 $%.%74:-0$4493 7/ !.88 098-70./439080.9433-7.

%#*!*$%%$%$ .

#.9:8    #..0*5439. 8/*807.05439*89. 8/*807./*807.9:8   $".  &% # ...05439*89.

/3:2-07 $%.9 17429.3 /85.-0 /-28*5. .:7847 & & $%%$$%  !*%* &%!&% $"*7.*.  &%  $"800.

%#*!*$%%$%$ .

3.943 /03910/-4507.05439*89.# ..:0   / 507.. &% # .943..943/   .20$9.9:8   #.9031472. 8/*807.05439*89.088 490  $*$#'! %*$%%&$  # $*$#'! %*$%%&$   . 8/*807...9:8   !./8 $ #%#%    !*%* &%!&% $%%#% #     #$*$#'*! %*    !70/./*807.8.0*5439.798 #48 #48 %20:11078#0...

88 098-70.098 $%./439080.%74:-0$4493 9 !.9433-7..

%#*!*$%%$%$ .

0*5439.9:8    #./*807. 8/*807. #.05439*89.05439*89..9:8   $"...  &% # . 8/*807.

*.-0 /-28*5.9 17429. .  &%  $"800.:7847 & & $%%$$%  !*%* &%!&% $"*7./3:2-07 $%.3 /85.

%#*!*$%%$%$ .

.9:8   !.798 #48 #48 %20:11078#0.:0   / 507.# ...20$9.943/   .3.05439*89.8.9031472. &% # . 8/*807. 8/*807.088 490  $*$#'! %*$%%&$  # $*$#'! %*$%%&$   ./*807.0*5439.943./8 $ #%#%    !*%* &%!&% $%%#% #     #$*$#'*! %*    !70/.05439*89.9:8   #...943 /03910/-4507...

88 $%.%74:-0$4493 9 !.

%#*!*$%%$%$ .

0*5439....05439*89.9:8  # . 8/*807.9:8 $".0*950 . 8/*807./*807..05439*89. #  . 8/*4. 8/*807...9:8  .0*950 .:50/*89. 8/*807.  &% # .

*./6/ .  &%    $"800.-0 /-28*5.9 17429.:7847 & & $%%$$%              !*%* &%!&% $"*./3:2-07 $%.3 /85.8.

%#*!*$%%$%$ .

.943.0*950  .3.8. &% # .0*950   ...05439*89..9:8     !. 8/*807.0*5439.798 #48 #48 %20:11078#0.05439*89. 8/*807.9:8   ./*807.943 /03910/-4507.9:8    # .20$9.#  .:0 / 507. 8/*807..9031472.943/   1907  $*$#'! %*$%%&$   $*$#'*%!  #  $* &!*$%%&$  $*$#'*%!   .:50/*89.. 8/*4.../8 !*%* &%!&% $ #%#%       %$$&*$#'*! %       !70/. 8/*807.

88 $%.%74:-0$4493 9 !.

%#*!*$%%$%$ .

05439*89.  &% # ..0*950   ./*807..0*5439. 8/*807. #  ..9:8     $". 8/*807.

 &%  $"800.3 /85./3:2-07 $%.9 17429.-0 /-28*5.*.:7847 & & $%%$$%  !*%* &%!&% $"*6/-61 .

%#*!*$%%$%$ .

20$9.. 8/*807.9:8     !.0*5439..0*950  ../*807..943.798 #48 #48 %20:11078#0./8 $ #%#%      $%&$*$#'*! %*      .:0 / 507.8.05439*89.#  .3. &% # . 8/*807.

%74:-0$4493 9 !.88 $%.

%#*!*$%%$%$ .

 &% # ..05439*89.9:8     $". 8/*807.. #  ..9:8    .0*5439./*807. 8/*4.0*950   .:50/*89.. 8/*807.

3 /85.:7847 & & $%%$$%  !*%* &%!&% $"*2 972 .  &%  $"800./3:2-07 $%.9 17429.*.-0 /-28*5.

%#*!*$%%$%$ .

/8 $ #%#%      %$$&*$#'*! %      .:50/*89.:0 / 507.0*5439.943.0*950   .9:8     !./*807..20$9..#  ... 8/*807. &% # .8..798 #48 #48 %20:11078#0.3. 8/*4.9:8   . 8/*807.05439*89.

7/3.90841 $%.42-3390.88 9..990..703 7.90892..789.550.88 19 !.3.08.7/3.90408.

%#*!*$%%$%$ .

8/*807.0*950   ../*807...9:8    .9:8     .  &% # .:50/*89.3/ $%. 8/*4. 8/*807.05439*89. #  ..0*5439.

%#*!*$%%$%$ .

8/*807.05439*89. #  .  &% # ./*807..0*950   . 8/*807..9:8     $"..0*5439.

 .

88 19 !.-0 982.4:/70 .989.84390*$#'*! %9.989.8 0.88 %47:04:989.425:9089.9089.3.4147.

-. /0.94382 #9 9.89*.9.94/49843.574/:.-0*3.0/ 380798 :5/.943 $"00.202 9./ 4..:94:1:8902439473 31472..-089 :807*9.-02439473803.-0*3.20  .204:79.7432039-:992.-0*3.3.:90$*$%%$ &$*%$* % #* %037:3 $%3:2*748 .908 /00908 # :807*9.20 9.7432039 43.984:/-0-/01.94303.88 19..-*24/1.-0/ .045203903.349-057.-03.

88 19 !.9089.-0 982.3.989.425:9089.8 0.4147.989.4:/70 .88 %47:04:989.84390*$#'*! %9.

3.94382 #9 9.0/ 9 9.984:/-0-/01.574/:.0/ $& 380798 $& :5/.204:79.045203903.89*.88 19.943 $"00..3. /0.-03.94303.7432039-:992.-*24/1.9.-.:90$*$%%$ &$*%$* % #* %037:3 $%9 9.:94:1:8902439473 31472.20 ./ 4.-0/ .20 92089.94/49843.908 $& /00908 # :807*9.349-057.-0*3.20 # &!9 9.-089 :807*9.89*.3..0/ .-02439473803..-0*3.-0*3.7432039 43.-0*3.202 9.25.89*.-0*3.20 .

38001742989.79.. 4:.:994574/:.994:/3 9-09.9/11.084209382.9 4781473/008  .

:.8 .9.4770.209..70570/...908 8:- 4592.88 %85.4770.9800.984205045017424:98/041 7.9:704190574-0289..0.0.39.9.98 3.99080..88 19 !.9083 3.:23..9 504501742 7.390700.79..9.90892..3.38  .943 .90/. /.703/0503/039 %8.90/ 90459207..903/0503/03.88:2089.4770.93.-0 147.43 90570/.90843908..0 .919070.5.7/3.9.788:08/4394.3/.88:25943 %00.4:238870.

03/897-:94341/.3/8 9070.7089.9/059-90 7.7838 .:/03.8    88:200.88:200.4.070/370.:8 4390 43.88 19 !.914. 800.9050450-473:3/07708947.07430390.98.3.9.308/08.422:399.3/8 050.80907.0348.88 %888:0.89.9.9.994 800 .8.8-003.78390070-473 :3/07   1.3/0.0.7-0898..

. .98  .7/3.

02-07947.783  .9.80907.3/30.9050450-473:3/07 708.97006:089438 $00.9.7.3/8.9 89.9050450-473 :3/077083.090.20147.9 2439  800.-4:9.9.3504507.9 243989. 42.80907.9.783 800.-4:99050450-473:3/07708357 .47/394 7.9.3/81....3807-0908.8147.

 .

.

 .9   .7/3.

0784341 7.0    ..  74:3/0/9447/0503/343.

.9.88 19 !.88 $4:94389490/.943.4770.3.

98.943 903/0/89.79..25090 /.9.0:808.907 89.7/8 98.943948.903/0503/03.0418.439.9.3370.:808 7.70.843...3/5.8.989.557457.9 $"574108 7.439.4:238...:9435.7/3.0 43.:/0 /3.:90906:073 47/0794.570/.00.25350714720//0503/84390 8.090459207/4390.33.484:94..7/8 .250/.9.0.8 411304592.88:25943 88:03.-036:070/ 900.7/8  7.2..2530..:942.8 7.9.043. 7.57410.0.98343..90//.253 43.989.0948..9:33  .90.0 39894147.331472.9000.

943 $:22.7  7.5&5 .$0.

.

   .

110.340/043094: 841.980.$:22.340/0 300/894-0.344/90.8 %8-0.3.338/08  .070/4390702.:20390/944/57.7 ...42243591.3..9.4.3/ 340/041.7 %4-0.99:33 4:790..0.

0.9.8 3 9072841/.7.9.3.:77039:8078 9238  !&.43.3/0/0130/5071472.%:33 -0..4:20 .08 $09.04.

90. 4.7098 #0202-079./3 4/44:344:..98 25479.70:92.894:9 9.99238.02094:74.399490-:83088  .

..2.7488.3:80909:33.0.3.55.. 4:78-0.0.:5909-4447.310.02039430/98 4349:80/3...0/9.5071472.3/.7-3..9:70.02039430/98 9.:098 43499:30:83 2..8479484.3..70410.0-0.3.%:33./...003..9430 80/40834919.5570.-:098 031.*8.07905.:808 -:9..909. 43495.559 -3/.4.88:204:.79...:80 ..01742903907309 /08. 574-02 -0.:80 7.943 4349.253.    $ $ %$%  .

7 1470.250 50..948.../8.3308847.2:99:/041838 %.3/03.0/-.70.948 97./94.041$"5071472320.%:339#.4 :  . 44/# #010794. ..:894297.941742  47.090-:1107.94 -.097...3 5071472498414.3/0.00.

989058.47/3%4%4290 %01443./   895488-09470/:.948.70-..2.9#..090 85747.854890/438%420.9.02-07     4:80/ 1 8.  108 .

0.4/3 347/0794 70/:.7094-01440/ 0.:/0308.

34:50.041$47!  09.30.250 -0:83 !..039..80/0243897. 15488-0 .909.98. 3:2-074190 8 8420507.4/ 8  ..

38 &/.$"147 .4/3 %.  .

0347.989. 749.3/8.0.88.9481474: 14:.:90.948$% ..7090 2.041.9.. %0708 4307..09884.8039047/ .94:80 84195.7432039.30.44/3:2-07 9809089:5/0897.9441902. .030890/445438.94 907. 749..9 126:07..43.09 .0 8/:0942.70 50703..3/48  8 903$ % 9.7/5..90479.07/4:-91:9.33/0 92:89-0-7403 ./*.948.097...94:300/9400.4:39479045920*3/0* 5.7808 984:/-030.33/084:/-0:80/  7..07 19.88.:5794198 14:.98890289 ./..7 147 2489889028 49077.5:-.0.9380 8479*.948 14709.96:07.07430949.70433.0599.0 2..-4:9902 %0708342.948 4.3/9739409 748-.4:/ -000.3/1470.70.0897430747/8-:9988..:9394:9/43  89030300/9419   .3.07  ./    -707934:7$" 9:334:7$" 8099303.3/90-0890 .209078  9050.-0 .*70..088.6:079.9 40.9#..7.030890/445438 09 907 8899070 .7807..70..3 9:83. 98.071470990.0.1907.*8047/-*10*2:9*-4.9441841994.01470.147:2.-094.47/3%4%4290 3/08.24390248954479:30/889028 %0.

943 995.91789.949.39#.9.20.94 %88.3085708039.74883...331:97.%0. 43.20.

.

425 /0243 . .4 :.

94 5/1     0.9*7.89  /0870/70854380920.

70854380920  .9:.. .

%:33 7.073 995....3$"9089.0.088019:339:338/0.0574/:./ $4.805.7093 7.8 7.0/....

.

4592072..42. -48549 .

 .

.

  .89 86:78.0/ 0.9:70.483 2 9.9:708. 938.7 92 .0700...4389.05943 03  .3/908941-:810/3 90459207    045920710.42084:9 /089.8-:8.07 7.0 8:55479 0058 .3-70.7.393974/:.808:3/07.70.47..3/1..80.07 10.8 -034 0.3/-4:3/.

/./0470/ 0.3/43.9380.70 247039070890/3/423.3/.%:33%03907309 $42047.3 /88023.2508 0  %4290.9574.808.7.08.0330 80./03.7..0 !701070-8908./.94385:-843903907309.9.38.93.3/ 050798 9.3/0.:20390/9089..308  .07983907-4489.074:3/0/430 /4.

3.7084:990704031.30 8947.388:08.:70 5..7.  .3.79.70078 30..3.0.:.84:94394.450 %08.248983907574108843.07.4504190574-02 470. 5071472.20907.088:044. .0574-0284:/ 2.0/9.8.250 .303/0 3/0.%:33 !74-02$..5071472.3300/9494:.9.0/-8420938:./:8934-8...9.30 08 9070.90203982470094-07084.209078.7$" 89.908.7.88902 /05.29.45041..:80/-4305..

55.0450 414:.89:30...09444/ 5071472.3 7..94:34 ..0 50347/  4349-3/5.36:08..90-499030.3/90 1903.08:3/074./ #010794.43/:.010.94:34 13/0709092084394 1789.559:3390.0.%:33.3.3.5 85708039.9:70.943435071472.3/903.78...943 49 -0.8411430-430  ..0 5.47/3 &3/0789.3/ 801742 7.

4.70438 /..3-..989.390.80 .3 3700.709 %0#$8.:.:78478 !..8 :.8033 302094/41..0 903/0/89.93/0389 !7490.4389.0.94:7801174298-9474:90893  .4300.59.%:3384.3%.

30..78309.&3/0789.0920 $07.3/#0854380%20 #0854380920.0920!&920433 5.039.. .9920.9343.9920 807.

36:08 8:.8.3 090708 .. &3/0789.3/98-..92:89-02 574-02 4741190945.9 4:78419.3/98.39.4941.943.0 907014709.2439473944.0398.3//7/43  .35.943 .4390994:7 .4/-3/8.9.709.4390394309.8443..3/8.55.. .06:.9907:390.980.

5503 40898.9 5 %020.0/  .088:09900330 98 /43 #52.9/7.7 03 .5071472.89.79.43889039 .308944:7.8 4:09.89807.43/9438/40898.20.9444...3.8 03//178989.3.989.55033 &3/07. 90708..574-.3.3.94:7.7 4:8..3.-.5503...9$9.09070-003.%:33'...

.43/9438/40894.0-.30.55..5071472.4:8 -0.3.9.3/.708003897.3/9388:..8 0708248941909204334:7.94383499.989.342.8 %0247.9$9.84:3/0789.98903472.%:33'.439094:300/94 .4:7 .989.0450 1474:7.9.:7:3/07  .803047 9 03...3 84..8394.943 .9:801: 347/07945:989.55.83089.943 84:934:.4198894789.989.

344:7%449 !071472.9:70 $ .3./.897:.0 95741 97..3/9092024/0 $"97..08  9:33317.0.8478  .8088 .0 $"0903/0/97.

9 8.3.38  .-99485491: 9.89448 489.84:/.709.-08.7803.43889412470 9.305.35..   $*! 4:79:33.3/90.

9 09.9478 2.33490  $.989.8.3/09-.98 09.    .3/0 -0.8 8947.9$9.9.8-44 09.9.90800.5907343.:890731.334908 .3/  !70/.3/98 98098...28 1706:03.:*89....3 08 8489.9.9.3.33490  3/06:.250808 :2-07841/893.0/ 09.40.:08 9.38/4349 :3/0789..33490  $890289.989.&3/0789.80/:3/.2039.

0#0.074:5-4 995.&801:3907309#084:7.3.08 %0 7.47/5071472..

9. 47 43.9:70//.9. 897:.308 8-4995.

.

43.42.9.308 47/57088 .

.0 5920774:54995. %0 7.

.

42.4592072. -48549 ..

37093 80-890 .42 0307.79.7174279.70.0074143.:.308 8 -44   ...03970. 41.05.9. 7.3 39433 995.5078 444:9147948035. .

.

 97./8 .42..

03.

422:39.34 4 .

/ .47390039103%0489 .7./434.80/ 59207 -34 4995. 92 %0$0.70.

.

 0.42./-9 .

$0.  .0 /4.39003.7.