The document provides tips for developing efficient SQL statements, including:
1. Choosing efficient join orders by joining tables with the best filters earliest and using indexes appropriately.
2. Being cautious when joining or reusing complex views, as it can result in entire views being instantiated.
3. Avoiding unnecessary scans and aggregations by combining multiple queries into a single query using CASE statements.
The document provides tips for developing efficient SQL statements, including:
1. Choosing efficient join orders by joining tables with the best filters earliest and using indexes appropriately.
2. Being cautious when joining or reusing complex views, as it can result in entire views being instantiated.
3. Avoiding unnecessary scans and aggregations by combining multiple queries into a single query using CASE statements.
The document provides tips for developing efficient SQL statements, including:
1. Choosing efficient join orders by joining tables with the best filters earliest and using indexes appropriately.
2. Being cautious when joining or reusing complex views, as it can result in entire views being instantiated.
3. Avoiding unnecessary scans and aggregations by combining multiple queries into a single query using CASE statements.
The document provides tips for developing efficient SQL statements, including:
1. Choosing efficient join orders by joining tables with the best filters earliest and using indexes appropriately.
2. Being cautious when joining or reusing complex views, as it can result in entire views being instantiated.
3. Avoiding unnecessary scans and aggregations by combining multiple queries into a single query using CASE statements.
With nested loop joins, the joins all happen through the join indexes, the indexes on the primary or foreign keys used to connect that table to an earlier table in the join tree. Rarely do you use the indexes on the non-join conditions, except for the driving table. Thus, after taba is chosen as the driving table, use the indexes on b.key1 and c.key2 to drive into tabb and tabc, respectively. 2. Choose the best join order, driving to the best unused filters earliest. The work of the following join can be reduced by first joining to the table with the best still-unused filter. Thus, if "bcol BETWEEN ..." is more restrictive (rejects a higher percentage of the rows seen) than "ccol BETWEEN ...", the last join can be made easier (with fewer rows) if tabb is joined before tabc. 3. You can use the ORDERED or STAR hint to force the join order. Use Caution When Managing Views Be careful when joining views, when performing outer joins to views, and when reusing an existing view for a new purpose. Use Caution When Joining Complex Views Joins to complex views are not recommended, particularly joins from one complex view to another. Often this results in the entire view being instantiated, and then the query is run against the view data. For example, the following statement creates a view that lists employees and departments: CREATE OR REPLACE VIEW emp_dept AS SELECT d.department_id, d.department_name, d.location_id, e.employee_id, e.last_name, e.first_name, e.salary, e.job_id FROM departments d ,employees e WHERE e.department_id (+) = d.department_id; The following query finds employees in a specified state: SELECT v.last_name, v.first_name, l.state_province FROM locations l, emp_dept v WHERE l.state_province = 'California' AND v.location_id = l.location_id (+); In the following plan table output, note that the emp_dept view is instantiated: -------------------------------------------------------------------------------- | Operation | Name | Rows | Bytes| Cost | Pstart| Pstop | -------------------------------------------------------------------------------- | SELECT STATEMENT | | | | | | | | FILTER | | | | | | | | NESTED LOOPS OUTER | | | | | | | | VIEW |EMP_DEPT | | | | | | | NESTED LOOPS OUTER | | | | | | | | TABLE ACCESS FULL |DEPARTMEN | | | | | | | TABLE ACCESS BY INDEX|EMPLOYEES | | | | | | | INDEX RANGE SCAN |EMP_DEPAR | | | | | | | TABLE ACCESS BY INDEX R|LOCATIONS | | | | | | | INDEX UNIQUE SCAN |LOC_ID_PK | | | | | | -------------------------------------------------------------------------------- See Also: "Hints for Join Orders" on page 16-4 Developing Efficient SQL Statements SQL Tuning Overview 11-15 Do Not Recycle Views Beware of writing a view for one purpose and then using it for other purposes to which it might be ill-suited. Querying from a view requires all tables from the view to be accessed for the data to be returned. Before reusing a view, determine whether all tables in the view need to be accessed to return the data. If not, then do not use the view. Instead, use the base table(s), or if necessary, define a new view. The goal is to refer to the minimum number of tables and views necessary to return the required data. Consider the following example: SELECT department_name FROM emp_dept WHERE department_id = 10; The entire view is first instantiated by performing a join of the employees and departments tables and then aggregating the data. However, you can obtain department_name and department_id directly from the departments table. It is inefficient to obtain this information by querying the emp_dept view. Use Caution When Unnesting Subqueries Subquery unnesting merges the body of the subquery into the body of the statement that contains it, allowing the optimizer to consider them together when evaluating access paths and joins. Use Caution When Performing Outer Joins to Views In the case of an outer join to a multi-table view, the query optimizer (in Release 8.1.6 and later) can drive from an outer join column, if an equality predicate is defined on it. An outer join within a view is problematic because the performance implications of the outer join are not visible. Store Intermediate Results Intermediate, or staging, tables are quite common in relational database systems, because they temporarily store some intermediate results. In many applications they are useful, but Oracle requires additional resources to create them. Always consider whether the benefit they could bring is more than the cost to create them. Avoid staging tables when the information is not reused multiple times. Some additional considerations: Storing intermediate results in staging tables could improve application performance. In general, whenever an intermediate result is usable by multiple following queries, it is worthwhile to store it in a staging table. The benefit of not retrieving data multiple times with a complex statement already at the second usage of the intermediate result is better than the cost to materialize it. Long and complex queries are hard to understand and optimize. Staging tables can break a complicated SQL statement into several smaller statements, and then store the result of each step. Consider using materialized views. These are precomputed tables comprising aggregated or joined data from fact and possibly dimension tables. See Also: Oracle Database Data Warehousing Guide for an explanation of the dangers with subquery unnesting See Also: Oracle Database Data Warehousing Guide for detailed information on using materialized views Developing Efficient SQL Statements 11-16 Oracle Database Performance Tuning Guide Restructuring the Indexes Often, there is a beneficial impact on performance by restructuring indexes. This can involve the following: Remove nonselective indexes to speed the DML. Index performance-critical access paths. Consider reordering columns in existing concatenated indexes. Add columns to the index to improve selectivity. Do not use indexes as a panacea. Application developers sometimes think that performance will improve if they create more indexes. If a single programmer creates an appropriate index, then this might indeed improve the application's performance. However, if 50 programmers each create an index, then application performance will probably be hampered. Modifying or Disabling Triggers and Constraints Using triggers consumes system resources. If you use too many triggers, then you can find that performance is adversely affected and you might need to modify or disable them. Restructuring the Data After restructuring the indexes and the statement, you can consider restructuring the data. Introduce derived values. Avoid GROUP BY in response-critical code. Review your data design. Change the design of your system if it can improve performance. Consider partitioning, if appropriate. Maintaining Execution Plans Over Time You can maintain the existing execution plan of SQL statements over time either using stored statistics or stored SQL execution plans. Storing optimizer statistics for tables will apply to all SQL statements that refer to those tables. Storing an execution plan (that is, plan stability) maintains the plan for a single SQL statement. If both statistics and a stored plan are available for a SQL statement, then the optimizer uses the stored plan. Visiting Data as Few Times as Possible Applications should try to access each row only once. This reduces network traffic and reduces database load. Consider doing the following: Combine Multiples Scans with CASE Statements Use DML with RETURNING Clause Modify All the Data Needed in One Statement See Also: Chapter 14, "Managing Optimizer Statistics" Chapter 18, "Using Plan Stability" Developing Efficient SQL Statements SQL Tuning Overview 11-17 Combine Multiples Scans with CASE Statements Often, it is necessary to calculate different aggregates on various sets of tables. Usually, this is done with multiple scans on the table, but it is easy to calculate all the aggregates with one single scan. Eliminating n-1 scans can greatly improve performance. Combining multiple scans into one scan can be done by moving the WHERE condition of each scan into a CASE statement, which filters the data for the aggregation. For each aggregation, there could be another column that retrieves the data. The following example asks for the count of all employees who earn less then 2000, between 2000 and 4000, and more than 4000 each month. This can be done with three separate queries: SELECT COUNT (*) FROM employees WHERE salary < 2000; SELECT COUNT (*) FROM employees WHERE salary BETWEEN 2000 AND 4000; SELECT COUNT (*) FROM employees WHERE salary>4000; However, it is more efficient to run the entire query in a single statement. Each number is calculated as one column. The count uses a filter with the CASE statement to count only the rows where the condition is valid. For example: SELECT COUNT (CASE WHEN salary < 2000 THEN 1 ELSE null END) count1, COUNT (CASE WHEN salary BETWEEN 2001 AND 4000 THEN 1 ELSE null END) count2, COUNT (CASE WHEN salary > 4000 THEN 1 ELSE null END) count3 FROM employees; This is a very simple example. The ranges could be overlapping, the functions for the aggregates could be different, and so on. Use DML with RETURNING Clause When appropriate, use INSERT, UPDATE, or DELETE... RETURNING to select and modify data with a single call. This technique improves performance by reducing the number of calls to the database. Modify All the Data Needed in One Statement When possible, use array processing. This means that an array of bind variable values is passed to Oracle for repeated execution. This is appropriate for iterative processes in which multiple rows of a set are subject to the same operation. For example: BEGIN FOR pos_rec IN (SELECT * FROM order_positions See Also: Oracle Database SQL Language Reference for syntax on the INSERT, UPDATE, and DELETE statements Developing Efficient SQL Statements 11-18 Oracle Database Performance Tuning Guide WHERE order_id = :id) LOOP DELETE FROM order_positions WHERE order_id = pos_rec.order_id AND order_position = pos_rec.order_position; END LOOP; DELETE FROM orders WHERE order_id = :id; END; Alternatively, you could define a cascading constraint on orders. In the previous example, one SELECT and n DELETEs are executed. When a user issues the DELETE on orders DELETE FROM orders WHERE order_id = :id, the database automatically deletes the positions with a single DELETE statement. See Also: Oracle Database Administrator's Guide or Oracle Database Heterogeneous Connectivity User's Guide for information on tuning distributed queries Automatic SQL Tuning 12-1 12 Automatic SQL Tuning This chapter discusses Oracle automatic SQL tuning features. This chapter contains the following sections: Automatic SQL Tuning Overview SQL Tuning Advisor SQL Tuning Sets SQL Profiles SQL Tuning Information Views Automatic SQL Tuning Overview Automatic SQL Tuning is a new capability of the query optimizer that automates the entire SQL tuning process. Using the newly enhanced query optimizer to tune SQL statements, the automatic process replaces manual SQL tuning, which is a complex, repetitive, and time-consuming function. The Automatic SQL Tuning features are exposed to the user with the SQL Tuning Advisor. This section covers the following topics: Query Optimizer Modes Types of Tuning Analysis Query Optimizer Modes The enhanced query optimizer has two modes: Normal mode Tuning mode Normal mode In normal mode, the optimizer compiles the SQL and generates an execution plan. The normal mode of the optimizer generates a reasonable execution plan for the vast majority of SQL statements. Under normal mode the optimizer operates with very strict time constraints, usually a fraction of a second, during which it must find a good execution plan. See Also: Oracle Database 2 Day DBA for information on monitoring and tuning SQL statements Automatic SQL Tuning Overview 12-2 Oracle Database Performance Tuning Guide Tuning mode In tuning mode, the optimizer performs additional analysis to check whether the execution plan produced under normal mode can be further improved. The output of the query optimizer is not an execution plan, but a series of actions, along with their rationale and expected benefit for producing a significantly superior plan. When called under the tuning mode, the optimizer is referred to as the Automatic Tuning Optimizer. The tuning performed by the Automatic Tuning Optimizer is called Automatic SQL Tuning. Under tuning mode, the optimizer can take several minutes to tune a single statement. It is both time and resource intensive to invoke the Automatic Tuning Optimizer every time a query has to be hard-parsed. The Automatic Tuning Optimizer is meant to be used for complex and high-load SQL statements that have non-trivial impact on the entire system. The Automatic Database Diagnostic Monitor (ADDM) proactively identifies high-load SQL statements which are good candidates for Automatic SQL Tuning. See Chapter 6, "Automatic Performance Diagnostics". Types of Tuning Analysis Automatic SQL Tuning includes four types of tuning analysis: Statistics Analysis SQL Profiling Access Path Analysis SQL Structure Analysis Statistics Analysis The query optimizer relies on object statistics to generate execution plans. If these statistics are stale or missing, the optimizer does not have the necessary information it needs and can generate poor execution plans. The Automatic Tuning Optimizer checks each query object for missing or stale statistics, and produces two types of output: Recommendations to gather relevant statistics for objects with stale or no statistics. Because optimizer statistics are automatically collected and refreshed, this problem may be encountered only when automatic optimizer statistics collection has been turned off. See "Automatic Statistics Gathering" on page 14-2. Auxiliary information in the form of statistics for objects with no statistics, and statistic adjustment factor for objects with stale statistics. This auxiliary information is stored in an object called a SQL Profile. SQL Profiling The query optimizer can sometimes produce inaccurate estimates about an attribute of a statement due to lack of information, leading to poor execution plans. Traditionally, users have corrected this problem by manually adding hints to the application code to guide the optimizer into making correct decisions. For packaged applications, changing application code is not an option and the only alternative available is to log a bug with the application vendor and wait for a fix. Automatic SQL Tuning deals with this problem with its SQL Profiling capability. The Automatic Tuning Optimizer creates a profile of the SQL statement called a SQL Profile, consisting of auxiliary statistics specific to that statement. The query optimizer under normal mode makes estimates about cardinality, selectivity, and cost that can sometimes be off by a significant amount resulting in poor execution plans. SQL Automatic SQL Tuning Overview Automatic SQL Tuning 12-3 Profile addresses this problem by collecting additional information using sampling and partial execution techniques to verify and, if necessary, adjust these estimates. During SQL Profiling, the Automatic Tuning Optimizer also uses execution history information of the SQL statement to appropriately set optimizer parameter settings, such as changing the OPTIMIZER_MODE initialization parameter setting from ALL_ ROWS to FIRST_ROWS for that SQL statement. The output of this type of analysis is a recommendation to accept the SQL Profile. A SQL Profile, once accepted, is stored persistently in the data dictionary. Note that the SQL Profile is specific to a particular query. If accepted, the optimizer under normal mode uses the information in the SQL Profile in conjunction with regular database statistics when generating an execution plan. The availability of the additional information makes it possible to produce well-tuned plans for corresponding SQL statement without requiring any change to the application code. The scope of a SQL Profile can be controlled by the CATEGORY profile attribute. This attribute determines which user sessions can apply the profile. You can view the CATEGORY attribute for a SQL Profile in CATEGORY column of the DBA_SQL_ PROFILES view. By default, all profiles are created in the DEFAULT category. This means that all user sessions where the SQLTUNE_CATEGORY initialization parameter is set to DEFAULT can use the profile. By altering the category of a SQL profile, you can determine which sessions are affected by the creation of a profile. For example, by setting the category of a SQL Profile to DEV, only those users sessions where the SQLTUNE_CATEGORY initialization parameter is set to DEV can use the profile. All other sessions do not have access to the SQL Profile and execution plans for SQL statements are not impacted by the SQL profile. This technique enables you to test a SQL Profile in a restricted environment before making it available to other user sessions. It is important to note that the SQL Profile does not freeze the execution plan of a SQL statement, as done by stored outlines. As tables grow or indexes are created or dropped, the execution plan can change with the same SQL Profile. The information stored in it continues to be relevant even as the data distribution or access path of the corresponding statement change. However, over a long period of time, its content can become outdated and would have to be regenerated. This can be done by running Automatic SQL Tuning again on the same statement to regenerate the SQL Profile. SQL Profiles apply to the following statement types: SELECT statements UPDATE statements INSERT statements (only with a SELECT clause) DELETE statements CREATE TABLE statements (only with the AS SELECT clause) MERGE statements (the update or insert operations) A complete set of functions are provided for management of SQL Profiles. See "SQL Profiles" on page 12-13. See Also: Oracle Database Reference for information on the SQLTUNE_CATEGORY initialization parameter SQL Tuning Advisor 12-4 Oracle Database Performance Tuning Guide Access Path Analysis Indexes can tremendously enhance performance of a SQL statement by reducing the need for full table scans on large tables. Effective indexing is a common tuning technique. The Automatic Tuning Optimizer also explores whether a new index can significantly enhance the performance of a query. If such an index is identified, it recommends its creation. Because the Automatic Tuning Optimizer does not analyze how its index recommendation can affect the entire SQL workload, it also recommends running a the SQLAccess Advisor utility on the SQL statement along with a representative SQL workload. The SQLAccess Advisor looks at the impact of creating an index on the entire SQL workload before making any recommendations. See "Automatic SQL Tuning Features" on page 11-5. SQL Structure Analysis The Automatic Tuning Optimizer identifies common problems with structure of SQL statements than can lead to poor performance. These could be syntactic, semantic, or design problems with the statement. In each of these cases the Automatic Tuning Optimizer makes relevant suggestions to restructure the SQL statements. The alternative suggested is similar, but not equivalent, to the original statement. For example, the optimizer may suggest to replace UNION operator with UNION ALL or to replace NOT IN with NOT EXISTS. An application developer can then determine if the advice is applicable to their situation or not. For instance, if the schema design is such that there is no possibility of producing duplicates, then the UNION ALL operator is much more efficient than the UNION operator. These changes require a good understanding of the data properties and should be implemented only after careful consideration. SQL Tuning Advisor The Automatic SQL Tuning capabilities are exposed through a server utility called the SQL Tuning Advisor. The SQL Tuning Advisor takes one or more SQL statements as an input and invokes the Automatic Tuning Optimizer to perform SQL tuning on the statements. The output of the SQL Tuning Advisor is in the form of an advice or recommendations, along with a rationale for each recommendation and its expected benefit. The recommendation relates to collection of statistics on objects, creation of new indexes, restructuring of the SQL statement, or creation of SQL Profile. A user can choose to accept the recommendation to complete the tuning of the SQL statements. The SQL Tuning Advisor input can be a single SQL statement or a set of statements. For tuning multiple statements, a SQL Tuning Set (STS) has to be first created. An STS is a database object that stores SQL statements along with their execution context. An STS can be created manually using command line APIs or automatically using Oracle Enterprise Manager. See "SQL Tuning Sets" on page 12-9. This section cover the following topics related to the SQL Tuning Advisor: Input Sources Tuning Options Advisor Output Using SQL Tuning Advisor APIs SQL Tuning Advisor Automatic SQL Tuning 12-5 Input Sources The input for the SQL Tuning Advisor can come from several sources. These input sources include: Automatic Database Diagnostic Monitor The primary input source is the Automatic Database Diagnostic Monitor (ADDM). By default, ADDM runs proactively once every hour and analyzes key statistics gathered by the Automatic Workload Repository (AWR) over the last hour to identify any performance problems including high-load SQL statements. If a high-load SQL is identified, ADDM recommends running SQL Tuning Advisor on the SQL. See "Automatic Database Diagnostic Monitor" on page 6-2. High-load SQL statements The second most important input source is the high-load SQL statements captured in Automatic Workload Repository (AWR). The AWR takes regular snapshots of the system activity including high-load SQL statements ranked by relevant statistics, such as CPU consumption and wait time. A user can view the AWR and identify the high-load SQL of interest and run SQL Tuning Advisor on them. By default, the AWR retains data for the last seven days. This means that any high-load SQL that ran within the retention period of the AWR can be located and tuned using this feature. See "Overview of the Automatic Workload Repository" on page 5-7. Cursor cache The third likely source of input is the cursor cache. This source is used for tuning recent SQL statements that are yet to be captured in the AWR. The cursor cache and AWR together provide the capability to identify and tune high-load SQL statements from the current time going as far back as the AWR retention allows, which by default is at least 7 days. SQL Tuning Set Another possible input source for the SQL Tuning Advisor is the SQL Tuning Set. A SQL Tuning Set (STS) is a database object that stores SQL statements along with their execution context. An STS can include SQL statements that are yet to be deployed, with the goal of measuring their individual performance, or identifying the ones whose performance falls short of expectation. When a set of SQL statements are used as input, a SQL Tuning Set (STS) has to be first constructed and stored. See "SQL Tuning Sets" on page 12-9. Tuning Options SQL Tuning Advisor provides options to manage the scope and duration of a tuning task. The scope of a tuning task can be set to limited or comprehensive. If the limited option is chosen, the SQL Tuning Advisor produces recommendations based on statistics checks, access path analysis, and SQL structure analysis. SQL Profile recommendations are not generated. If the comprehensive option is selected, the SQL Tuning Advisor carries out all the analysis it performs under limited scope plus SQL Profiling. With the comprehensive option you can also specify a time limit for the tuning task, which by default is 30 minutes. SQL Tuning Advisor 12-6 Oracle Database Performance Tuning Guide Advisor Output After analyzing the SQL statements, the SQL Tuning Advisor provides advice on optimizing the execution plan, the rationale for the proposed optimization, the estimated performance benefit, and the command to implement the advice. You simply have to choose whether or not to accept the recommendations to optimize the SQL statements. Using SQL Tuning Advisor APIs The recommended interface for running the SQL Tuning Advisor is the Oracle Enterprise Manager. Whenever possible, you should run the SQL Tuning Advisor using Oracle Enterprise Manager, as described in the Oracle Database 2 Day + Performance Tuning Guide. If Oracle Enterprise Manager is unavailable, you can run the SQL Tuning Advisor using procedures in the DBMS_SQLTUNE package. To use the APIs, the user must be granted specific privileges. Running SQL Tuning Advisor using DBMS_SQLTUNE package is a multi-step process: 1. Create a SQL Tuning Set (if tuning multiple SQL statements) 2. Create a SQL tuning task 3. Execute a SQL tuning task 4. Display the results of a SQL tuning task 5. Implement recommendations as appropriate A SQL tuning task can be created for a single SQL statement. For tuning multiple statements, a SQL Tuning Set (STS) has to be first created. An STS is a database object that stores SQL statements along with their execution context. An STS can be created manually using command line APIs or automatically using Oracle Enterprise Manager. See "SQL Tuning Sets" on page 12-9. Figure 121 shows the steps involved when running the SQL Tuning Advisor using the DBMS_SQLTUNE package. See Also: Oracle Database PL/SQL Packages and Types Reference for information on the security model for the DBMS_SQLTUNE package