Oracle's SQL statement performance optimization (34 optimization methods)

(1) Choose the most efficient table name order (only valid in the rule-based optimizer):

ORACLE's parser processes the table names in the FROM clause in a right-to-left order. The last table written in the FROM clause (basic table driving table) will be processed first, and multiple tables are included in the FROM clause. In this case, you must select the table with the least number of records as the base table. If there are more than 3 tables to join the query, then you need to select the intersection table as the base table, and the intersection table refers to the table that is referenced by other tables.

(2) The join order in the WHERE clause. :

ORACLE parses the WHERE clause in a bottom-up order. According to this principle, the connection between tables must be written before other WHERE conditions, and those conditions that can filter out the maximum number of records must be written at the end of the WHERE clause.

(3) Avoid using ' * ' in the SELECT clause:

In the process of parsing, ORACLE will convert '*' into all column names in turn. This work is done by querying the data dictionary, which means that it will take more time

(4) Reduce the number of times the database is accessed:

ORACLE performs a lot of work internally: parsing SQL statements, estimating index utilization, binding variables, reading data blocks, etc.;

(5) Resetting the ARRAYSIZE parameter in SQL*Plus, SQL*Forms and Pro*C can increase the amount of retrieved data for each database access, the recommended value is 200

(6) Use the DECODE function to reduce processing time:

Use the DECODE function to avoid repeatedly scanning the same records or repeatedly joining the same table.

(7) Integrate simple, unrelated database access:

If you have several simple database query statements, you can combine them into one query (even if there is no relationship between them)

(8) Delete duplicate records:

 

Example of the most efficient way to remove duplicate records (because ROWID is used):

1
2
DELETE FROM EMP E WHERE E.ROWID > ( SELECT MIN (X.ROWID)
FROM EMP X WHERE X.EMP_NO = E.EMP_NO);

 

(9) Replace DELETE with TRUNCATE:

When deleting records in a table, under normal circumstances, rollback segments are used to store information that can be recovered. If you do not have a COMMIT transaction, ORACLE will restore the data to the state before the deletion (to be precise, restore to the state before the delete command was executed) and when TRUNCATE is used, the rollback segment no longer stores any recoverable information. When the command is run, the data cannot be recovered. Therefore, few resources are called, and the execution time will also be Very short.

(10) Use COMMIT as much as possible:

Whenever possible, use COMMIT as much as possible in the program, so that the performance of the program is improved, and the demand will be reduced due to the resources
released by COMMIT: The resources released by COMMIT:

a. Information on the rollback segment used to restore data.

b. Locks acquired by program statements

c. Space in redo log buffer

d. ORACLE manages the internal costs of the above three resources

(11) Replace the HAVING clause with the Where clause:

Avoid using the HAVING clause, HAVING will only filter the result set after all records have been retrieved. This processing requires sorting, totaling, etc. If you can limit the number of records by the WHERE clause, you can reduce this overhead. . (non-oracle) among the three clauses that can add conditions to on, where, and having, on is the first to execute, where is second, and having is last, because on is to filter the records that do not meet the conditions before proceeding. Statistics, it can reduce the data to be processed by the intermediate operation. It is reasonable to say that the speed should be the fastest, and where should be faster than having, because it does sum after filtering data, and only uses on when two tables are joined. , so in a table, only where is left to compare with having. In the case of this single table query statistics, if the conditions to be filtered do not involve the fields to be calculated, then their results are the same, but the rushmore technique can be used where, but having cannot, the latter is slower in terms of speed. If the calculated field is involved, it means that the value of this field is uncertain before it is calculated. According to the workflow written in the previous article, the action time of where is completed before the calculation, and the having is only after the calculation. works, so in this case the results of the two will be different. In multi-table join query, on works earlier than where. The system first combines multiple tables into a temporary table according to the join conditions between each table, then filters by where, and then calculates, and then filters by having. It can be seen that in order for the filter condition to play a correct role, we must first understand when the condition should work, and then decide where to put it.

(12) Reduce the query to the table:

In SQL statements containing subqueries, special attention should be paid to reducing the number of queries to the table. Example:

1
2
   SELECT TAB_NAME FROM TABLES WHERE (TAB_NAME,DB_VER) = ( SELECT
TAB_NAME,DB_VER FROM TAB_COLUMNS WHERE VERSION = 604)

 

(13) Improve SQL efficiency through internal functions.:

Complex SQL often sacrifices execution efficiency. It is very meaningful to be able to master the above methods of using functions to solve problems in practical work

(14) Use the alias of the table (Alias):

When joining multiple tables in an SQL statement, use table aliases and prefix each column with the alias. This reduces parsing time and reduces syntax errors caused by column ambiguity.

(15) Replace IN with EXISTS and NOT IN with NOT EXISTS:

In many queries based on underlying tables, it is often necessary to join another table in order to satisfy one condition. In this case, using EXISTS (or NOT EXISTS ) will usually improve the efficiency of the query. In subqueries, NOT IN clause will perform an internal sort and merge. In either case, NOT IN is the least efficient (since it performs a full table traversal of the tables in the subquery). To avoid using NOT IN, we can Rewrite it as Outer Joins or NOT EXISTS.

example:

1
 
 
 
2
(高效) SELECT * FROM EMP (基础表) WHERE EMPNO > 0
AND EXISTS ( SELECT ‘X ' FROM DEPT WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = ‘MELB' )
 
(低效) SELECT * FROM EMP (基础表) WHERE EMPNO > 0
AND DEPTNO IN ( SELECT DEPTNO FROM DEPT WHERE LOC = ‘MELB')
 

 

(16) Identify 'inefficiently executed' SQL statements:

Although various graphical tools for SQL optimization emerge in an endless stream, it is always the best way to write your own SQL tool to solve the problem:

1
2
3
4
5
6
7
8
9
SELECT EXECUTIONS , DISK_READS, BUFFER_GETS,
ROUND((BUFFER_GETS-DISK_READS)/BUFFER_GETS,2) Hit_radio,
ROUND(DISK_READS/EXECUTIONS,2) Reads_per_run,
SQL_TEXT
FROM V$SQLAREA
WHERE EXECUTIONS>0
AND BUFFER_GETS > 0
AND (BUFFER_GETS-DISK_READS)/BUFFER_GETS < 0.8
ORDER BY 4 DESC ;

 

(17) Use indexes to improve efficiency:

An index is a conceptual part of a table that is used to improve the efficiency of retrieving data. ORACLE uses a complex self-balancing B-tree structure. Generally, querying data through an index is faster than a full table scan. When ORACLE finds out, execute the query and Update The ORACLE optimizer will use an index when determining the best path for a statement. Also, using an index can improve efficiency when joining multiple tables. Another benefit of using an index is that it provides primary key uniqueness verification. For those LONG or LONG RAW data types, you can index almost any column. In general, using an index is especially effective on large tables. Of course, you will also find that when scanning small tables, using an index can also improve efficiency. Although using an index The query efficiency can be improved, but we must also pay attention to its cost. The index needs space for storage and regular maintenance. Whenever a record is added or deleted in the table or the index column is modified, the index itself will also be modified. . This means that INSERT, DELETE, UPDATE of each record will cost 4 or 5 more disk I/Os for this. Because indexes require additional storage space and processing, those unnecessary indexes will make query response time worse. slow.. Periodically rebuilding the index is necessary.:

1
ALTER INDEX <INDEXNAME> REBUILD <TABLESPACENAME>

 

(18) Replace DISTINCT with EXISTS:

When submitting a query that contains one-to-many table information (such as department and employees), avoid using DISTINCT in the SELECT clause. You can generally consider replacing it with EXIST. EXISTS makes the query faster because the RDBMS core module will Once the conditions of the subquery are met, the results are returned immediately. Example:

1
2
3
  (低效):
SELECT DISTINCT DEPT_NO,DEPT_NAME FROM DEPT D , EMP E
WHERE D.DEPT_NO = E.DEPT_NO
1
2
3
(高效):
SELECT DEPT_NO,DEPT_NAME FROM DEPT D WHERE EXISTS ( SELECT ‘X'
FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO);

 

(19) Use uppercase for sql statements; because oracle always parses sql statements first, converts lowercase letters to uppercase, and executes them

(20) Use the connector "+" to connect strings as little as possible in java code!

(21) Avoid using NOT on indexed columns Typically, 

We want to avoid using NOT on indexed columns, NOT will have the same effect as using functions on indexed columns. When ORACLE "encounters" NOT, it will stop using the index and perform a full table scan instead.

(22) Avoid using calculations on indexed columns.

In the WHERE clause, if the indexed column is part of the function. The optimizer will use full table scans instead of indexes.

Example:

1
2
低效:
SELECT FROM DEPT WHERE SAL * 12 > 25000;
1
2
高效:
SELECT FROM DEPT WHERE SAL > 25000/12;

 

(23) Replace > with >=

1
2
高效:
SELECT * FROM EMP WHERE DEPTNO >=4
1
2
低效:
SELECT * FROM EMP WHERE DEPTNO >3

The difference between the two is that the former DBMS will jump directly to the first record with DEPT equal to 4 while the latter will first locate the record with DEPTNO=3 and scan forward to the first record with DEPT greater than 3.

 

(24) Replace OR with UNION (for indexed columns)

In general, replacing OR in the WHERE clause with UNION will work better. Using OR on indexed columns will result in a full table scan. Note that the above rules are only valid for multiple indexed columns. Index, query efficiency may be reduced because you do not select OR. In the following example, both LOC_ID and REGION are indexed.

1
2
3
4
5
6
7
8
高效:
SELECT LOC_ID , LOC_DESC , REGION
FROM LOCATION
WHERE LOC_ID = 10
UNION
SELECT LOC_ID , LOC_DESC , REGION
FROM LOCATION
WHERE REGION = “MELBOURNE”

1
2
3
4
低效:
SELECT LOC_ID , LOC_DESC , REGION
FROM LOCATION
WHERE LOC_ID = 10 OR REGION = “MELBOURNE”

If you insist on using OR, you need to write the index column with the fewest returned records first.

(25) Replace OR with IN 

This is a simple and easy-to-remember rule, but the actual execution effect needs to be checked. Under ORACLE8i, the execution paths of the two seem to be the same. 

1
2
低效:
SELECT …. FROM LOCATION WHERE LOC_ID = 10 OR LOC_ID = 20 OR LOC_ID = 30

1
2
高效
SELECT FROM LOCATION WHERE LOC_IN IN (10,20,30);

 

(26) Avoid using IS NULL and IS NOT NULL on indexed columns

避免在索引中使用任何可以为空的列,ORACLE将无法使用该索引.对于单列索引,如果列包含空值,索引中将不存在此记录. 对于复合索引,如果每个列都为空,索引中同样不存在此记录. 如果至少有一个列不为空,则记录存在于索引中.举例: 如果唯一性索引建立在表的A列和B列上, 并且表中存在一条记录的A,B值为(123,null) , ORACLE将不接受下一条具有相同A,B值(123,null)的记录(插入). 然而如果所有的索引列都为空,ORACLE将认为整个键值为空而空不等于空. 因此你可以插入1000 条具有相同键值的记录,当然它们都是空! 因为空值不存在于索引列中,所以WHERE子句中对索引列进行空值比较将使ORACLE停用该索引.

1
2
低效: (索引失效)
SELECT FROM DEPARTMENT WHERE DEPT_CODE IS NOT NULL ;
1
2
高效: (索引有效)
SELECT FROM DEPARTMENT WHERE DEPT_CODE >=0;

 

(27) 总是使用索引的第一个列:

如果索引是建立在多个列上, 只有在它的第一个列(leading column)被where子句引用时,优化器才会选择使用该索引. 这也是一条简单而重要的规则,当仅引用索引的第二个列时,优化器使用了全表扫描而忽略了索引

(28) 用UNION-ALL 替换UNION ( 如果有可能的话):

当SQL语句需要UNION两个查询结果集合时,这两个结果集合会以UNION-ALL的方式被合并, 然后在输出最终结果前进行排序. 如果用UNION ALL替代UNION, 这样排序就不是必要了. 效率就会因此得到提高. 需要注意的是,UNION ALL 将重复输出两个结果集合中相同记录. 因此各位还是要从业务需求分析使用UNION ALL的可行性. UNION 将对结果集合排序,这个操作会使用到SORT_AREA_SIZE这块内存. 对于这块内存的优化也是相当重要的. 下面的SQL可以用来查询排序的消耗量

1
2
3
4
5
6
7
8
低效:
SELECT ACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = '31-DEC-95'
UNION
SELECT ACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = '31-DEC-95'
1
2
3
4
5
6
7
8
高效:
SELECT ACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = '31-DEC-95'
UNION ALL
SELECT ACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = '31-DEC-95'

(29) 用WHERE替代ORDER BY:

ORDER BY 子句只在两种严格的条件下使用索引.
ORDER BY中所有的列必须包含在相同的索引中并保持在索引中的排列顺序.
ORDER BY中所有的列必须定义为非空.
WHERE子句使用的索引和ORDER BY子句中所使用的索引不能并列.

例如:

表DEPT包含以下列:

DEPT_CODE PK NOT NULL
DEPT_DESC NOT NULL
DEPT_TYPE NULL

1
2
低效: (索引不被使用)
SELECT DEPT_CODE FROM DEPT ORDER BY DEPT_TYPE
1
2
高效: (使用索引)
SELECT DEPT_CODE FROM DEPT WHERE DEPT_TYPE > 0

 

(30) 避免改变索引列的类型.:

当比较不同数据类型的数据时, ORACLE自动对列进行简单的类型转换.

假设 EMPNO是一个数值类型的索引列.

1
SELECT FROM EMP WHERE EMPNO = ‘123'

 

实际上,经过ORACLE类型转换, 语句转化为:

1
SELECT FROM EMP WHERE EMPNO = TO_NUMBER(‘123')

幸运的是,类型转换没有发生在索引列上,索引的用途没有被改变.

现在,假设EMP_TYPE是一个字符类型的索引列.

1
SELECT FROM EMP WHERE EMP_TYPE = 123

 

这个语句被ORACLE转换为:

1
SELECT FROM EMP WHERETO_NUMBER(EMP_TYPE)=123

因为内部发生的类型转换, 这个索引将不会被用到! 为了避免ORACLE对你的SQL进行隐式的类型转换, 最好把类型转换用显式表现出来. 注意当字符和数值比较时, ORACLE会优先转换数值类型到字符类型

(31) 需要当心的WHERE子句:

某些SELECT 语句中的WHERE子句不使用索引. 这里有一些例子.

在下面的例子里, (1)‘!=' 将不使用索引. 记住, 索引只能告诉你什么存在于表中, 而不能告诉你什么不存在于表中. (2) ‘||'是字符连接函数. 就象其他函数那样, 停用了索引. (3) ‘+'是数学函数. 就象其他数学函数那样, 停用了索引. (4)相同的索引列不能互相比较,这将会启用全表扫描.

(32)a. 如果检索数据量超过30%的表中记录数.使用索引将没有显著的效率提高.

b. 在特定情况下, 使用索引也许会比全表扫描慢, 但这是同一个数量级上的区别. 而通常情况下,使用索引比全表扫描要块几倍乃至几千倍!

(33) 避免使用耗费资源的操作:

带有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY的SQL语句会启动SQL引擎

执行耗费资源的排序(SORT)功能. DISTINCT需要一次排序操作, 而其他的至少需要执行两次排序. 通常, 带有UNION, MINUS , INTERSECT的SQL语句都可以用其他方式重写. 如果你的数据库的SORT_AREA_SIZE调配得好, 使用UNION , MINUS, INTERSECT也是可以考虑的, 毕竟它们的可读性很强

(34) 优化GROUP BY:

提高GROUP BY 语句的效率, 可以通过将不需要的记录在GROUP BY 之前过滤掉.下面两个查询返回相同结果但第二个明显就快了许多.

1
2
3
4
5
6
低效:
SELECT JOB , AVG (SAL)
FROM EMP
GROUP JOB
HAVING JOB = ‘PRESIDENT '
OR JOB = ‘MANAGER'
1
2
3
4
5
6
高效:
SELECT JOB , AVG (SAL)
FROM EMP
WHERE JOB = ‘PRESIDENT '
OR JOB = ‘MANAGER'
GROUP JOB

 

文章出自:http://www.cnblogs.com/rootq/archive/2008/11/17/1334727.html

 

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326912149&siteId=291194637