Oracle-sql statement optimization points

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 right-to-left order, so the table written last in the FROM clause (the underlying table driving table) will be processed first. Include multiple in the FROM clause In the case of tables, you must select the table with the least number of records as the base table. When ORACLE processes multiple tables, it will use sorting and merging to join them. First, scan the first table (the last one in the FROM clause). that table) and dispatch the records, then scan the second table (the last second table in the FROM clause), and finally compare all the records retrieved from the second table with the appropriate records in the first table merge.
	E.g:       
		Table TAB1 16,384 records
		Table TAB2 1 record
		
	Select TAB2 as base table (best way)
		select count(*) from tab1,tab2; execution time 0.96 seconds
	Select TAB2 as base table (poor approach)
		select count(*) from tab2,tab1; execution time 26.09 seconds
		
	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.
		For example: EMP table describes the intersection of LOCATION table and CATEGORY table.
			SELECT *
			FROM LOCATION L, CATEGORY C, EMP E
			WHERE E.EMP_NO BETWEEN 1000 AND 2000
				AND E.CAT_NO = C.CAT_NO
				AND E.LOCN = L.LOCN;
				
		will be more efficient than the following SQL
			SELECT *
			FROM EMP E, LOCATION L, CATEGORY C
			WHERE E.CAT_NO = C.CAT_NO
			   AND E.LOCN = L.LOCN
			   AND E.EMP_NO BETWEEN 1000 AND 2000;
		  
2 Join order in 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.
	E.g:
		(inefficient, execution time 156.3 seconds)
		SELECT * FROM EMP E WHERE SAL > 50000 AND JOB = ‘MANAGER’ AND 25 < (SELECT COUNT(*) FROM EMP WHERE MGR = E.EMPNO);
		
		(efficient, execution time 10.6 seconds)
		SELECT * FROM EMP E WHERE 25 < (SELECT COUNT(*) FROM EMP WHERE MGR=E.EMPNO) AND SAL > 50000 AND JOB = ‘MANAGER’;

3 Avoid using "*" in the SELECT clause
	Using the dynamic SQL column reference '*' is a convenient method when you want to list all COLUMNs in the SELECT clause. Unfortunately, this is a very inefficient method. , will convert '*' into all column names in turn, this work is done by querying the data dictionary, which means it will take more time.
	
4 Reduce the number of database visits
	When each SQL statement is executed, ORACLE performs a lot of work internally: parsing the SQL statement, estimating the utilization of indexes, binding variables, reading data blocks, etc. It can be seen that reducing the number of database accesses can actually Reduce ORACLE workload.
	E.g:
		There are three ways to retrieve employees whose employee number is equal to 0342 or 0291.
		Method 1 (least efficient)
			SELECT EMP_NAME,SALARY,GRADE FROM EMP WHERE EMP_NO = 342;
			SELECT EMP_NAME,SALARY,GRADE FROM EMP WHERE EMP_NO = 291;
			
		Method 2 (less efficient)
			DECLARE CURSOR C1 (E_NO NUMBER) IS
				SELECT EMP_NAME,SALARY,GRADE FROM EMP WHERE EMP_NO = E_NO;
			BEGIN
				OPEN C1(342);
				FETCH C1 INTO …,..,.. ;
				OPEN C1(291);
				FETCH C1 INTO …,..,.. ;
				CLOSE C1;
			END;
			
		Method 3 (efficient)
			SELECT
				A.EMP_NAME,
				A.SALARY,
				A.GRADE,
				B.EMP_NAME,
				B.SALARY,
				B.GRADE
			FROM
				EMP A,
				EMP B
			WHERE A.EMP_NO = 342 AND B.EMP_NO = 291;
	Notice:
		Resetting the ARRAYSIZE parameter in SQL*Plus, SQL*Forms and Pro*C can increase the amount of retrieved data per database access, the recommended value is 200.

5 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.
	E.g:
		SELECT COUNT(*) ,SUM(SAL) FROM EMP WHERE DEPT_NO = 0020 AND ENAME LIKE ‘SMITH%’;
		SELECT COUNT(*) ,SUM(SAL) FROM EMP WHERE DEPT_NO = 0030 AND ENAME LIKE ‘SMITH%’;
		
	You can get the same result efficiently with the DECODE function
		SELECT COUNT(DECODE(DEPT_NO, 0020, ’X’, NULL)) D0020_COUNT,
			   COUNT(DECODE(DEPT_NO, 0030, ’X’, NULL)) D0030_COUNT,
			   SUM(DECODE(DEPT_NO, 0020, SAL, NULL)) D0020_SAL,
			   SUM(DECODE(DEPT_NO, 0030, SAL, NULL)) D0030_SAL
		  FROM EMP
		 WHERE ENAME LIKE ‘SMITH%’;
	Similarly, the DECODE function can also be used in GROUP BY and ORDER BY clauses.
	
	

6 Remove duplicate records. Focus on
	Most efficient way to remove duplicate records (because ROWID is used)
		DELETE FROM EMP E WHERE E.ROWID > (SELECT MIN(X.ROWID) FROM EMP X WHERE X.EMP_NO = E.EMP_NO);
		
7 Replace DELETE with TRUNCATE
	When deleting records in a table, under normal circumstances, rollback segments (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, recovery until the delete command was executed)
	When using TRUNCATE, the rollback segment no longer stores any recoverable information. When the command is run, the data cannot be recovered. Therefore, fewer resources are called and the execution time is very short.
	(Translator's note: TRUNCATE is only applicable to delete the whole table, TRUNCATE is DDL not DML)

8 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:
	Resources released by COMMIT:
		a. Information on the rollback segment used to restore data.
		b. Locks acquired by program statements
		space in the c.redo log buffer
		d.ORACLE manages the internal costs of the above three resources
		(Translator's Note: When using COMMIT, you must pay attention to the integrity of the transaction. In reality, efficiency and transaction integrity are often incompatible)
		
9 Reduce queries to tables
	In SQL statements containing subqueries, special attention should be paid to reducing the number of queries to the table.
	E.g:
	(inefficient)
		SELECT TAB_NAME
		FROM TABLES
		WHERE TAB_NAME = (SELECT TAB_NAME FROM TAB_COLUMNS WHERE VERSION = 604)
		AND DB_VER = (SELECT DB_VER FROM TAB_COLUMNS WHERE VERSION = 604)
	(efficient)
		SELECT TAB_NAME
		FROM TABLES
		WHERE (TAB_NAME, DB_VER) = (SELECT TAB_NAME, DB_VER) FROM TAB_COLUMNS
		WHERE VERSION = 604)
		
	Update multiple Column example:
	(inefficient)
		UPDATE EMP
		SET EMP_CAT = (SELECT MAX(CATEGORY) FROM EMP_CATEGORIES),
		SAL_RANGE = (SELECT MAX(SAL_RANGE) FROM EMP_CATEGORIES)
		WHERE EMP_DEPT = 0020;
		
	(efficient)
		UPDATE EMP
		   SET (EMP_CAT, SAL_RANGE) =
			   (SELECT MAX(CATEGORY), MAX(SAL_RANGE) FROM EMP_CATEGORIES)
		WHERE EMP_DEPT = 0020;

10 Replace IN with 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.
	Inefficient:
		SELECT *
		FROM EMP (base table)
		WHERE EMPNO >; 0
		AND DEPTNO IN (SELECT DEPTNO
		FROM DEPT
		WHERE LOC = ‘MELB’);
	Efficient:
		SELECT *
		FROM EMP (base table)
		WHERE EMPNO >; 0
		AND EXISTS (SELECT ‘X’
		FROM DEPT
		WHERE DEPT.DEPTNO = EMP.DEPTNO
		AND LOC = ‘MELB’)
	(Translator's note: Relatively speaking, replacing NOT IN with NOT EXISTS will improve efficiency more significantly, as will be pointed out in the next section)
	
11 Replace NOT IN with NOT EXISTS
	In a subquery, the NOT IN clause will perform an internal sort and merge. In either case, NOT IN is the least efficient (because it performs a full table traversal of the tables in the subquery). In order to Instead of using NOT IN, we can rewrite it as Outer Joins or NOT EXISTS.
	E.g:
		SELECT * FROM EMP WHERE DEPT_NO NOT IN (SELECT DEPT_NO FROM DEPT WHERE DEPT_CAT=’A’);
		
	In order to improve efficiency. Rewrite as:
	(Method 1: Efficient)
		SELECT * FROM EMP A, DEPT B WHERE A.DEPT_NO = B.DEPT(+) AND B.DEPT_NO IS NULL AND B.DEPT_CAT(+) = ‘A’

	(Method 2: The most efficient)
		SELECT * FROM EMP E
		WHERE NOT EXISTS (SELECT ‘X’ FROM DEPT D WHERE D.DEPT_NO = E.DEPT_NO AND DEPT_CAT = ‘A’);
	Of course, the most efficient method is to have a table association. The speed of the direct two-table relationship is the fastest!
	
12 Identifying 'inefficiently executed' SQL statements
	Use the following SQL tools to find inefficient SQL:
		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;

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326098995&siteId=291194637