Académique Documents
Professionnel Documents
Culture Documents
What is Tuning?
Performance Pyramid
Network
Hardware OS
DBMS
Application
a) Wrong Designs
b) ineffective SQLs written Do your developers know: Sub-queries (correlated and not) Outer Joins Minus Union and Union-All
Tuning as you go may be impractical, and after youre done it may be too late. Often its best to apply general tuning guidelines as you go, and then identify problem areas for improvement.
Everyone tune codes as per the knowledge they have developed with time. SQL Looks very simple but matter of fact is that even optimizer also work on intuition of the developers
Now What
Indexes
What are indexes? What are the type of Index available for me? How can they help me? What to Index ? What Not to Index ? Are they really good?
Cluster indexes, bitmap join indexes, function-based indexes, reverse key indexes and text indexes are all just variations on the two main types
What B-Stands in B-Tree?
Well the answer of this is bit trick. But still I will say sometimes indexes in oracle can get more scary then the monster we had seen in our dreams
Golden Rule #4: Use indexes but not with blind eye
[Index Not used] [Index Used] [Index Used] [Index Not used] [Index Not used] [Index Not used] [Index Not used] [Index Not used] [Index Used] [Index Not used] [Index Used] [Index Not used] [Index Used]
important under rule based optimizer, and won't hurt under cost based optimizer
order FROM clauses in descending order of table sizes based upon row counts for example select * from larger table, smaller table select * from larger table, smaller table, smallest table select * from larger table, smaller table, associative table
Bad: select distinct deptno, deptname from emp, dept where emp.deptno = dept.deptno
Good: select deptno, deptname from dept where exists (select X from emp where emp.deptno = dept.deptno)
SELECT E.EMPLOYEE_ID , E.FIRST_NAME , E.LAST_NAME , E.SALARY FROM EMPLOYEES E WHERE E.EMPLOYEE_ID IN (SELECT O.SALES_REP_ID FROM ORDERS O WHERE O.CUSTOMER_ID = 144)
26
avoid sub-queries that use NOT IN, use NOT EXISTS instead Bad: select * from emp where deptno not in (select deptno from dept where deptstatus = A) Good: select * from emp where not exists (select X from dept where deptstatus = A and dept.deptno = emp.deptno)
when counting rows, use COUNT on indexed column or asterisk select count(indexed_column) from table select count(*) from table Select count(non_indexed_column) from table select count(1) from table
[Most Efficient]
a dummy WHERE clause referencing an indexed column will retrieve all records in ascending order (descending for 8i descending index)
SELECT region, AVG (loc_size) FROM location GROUP BY region HAVING region != 'SYDNEY' AND region != 'PERTH'; SELECT region, AVG (loc_size) FROM location WHERE region != 'SYDNEY' AND region != 'PERTH'; GROUP BY region;
Rule #12: Minimize number to Table lookups SELECT emp_name FROM emp WHERE emp_cat = (SELECT MAX (category) FROM emp_categories) AND emp_range = (SELECT MAX (sal_range) FROM emp_categories) AND emp_dept = 0020; SELECT emp_name FROM emp WHERE (emp_cat, sal_range) = (SELECT MAX (category), MAX (sal_range)
31
Instead of:
SELECT * FROM t1, t2, t3 WHERE t1.emp_id = t2.emp_id AND t2.emp_id = t3.emp_id
add:
SELECT * FROM t1, t2, t3 WHERE t1.emp_id = t2.emp_id AND t2.emp_id = t3.emp_id AND t1.emp_id = t3.temp_id;
Syntax must be accurate - if not, hint is ignored If aliasing tables, must use alias in hint
Do not specify schema names in the hint even if they are specified in the FROM clause
33
/*+ FULL(table) */ /*+ INDEX(table index) */ Hints for Join Orders ORDERED
34
Golden Rule #5: Know your data, Know what youre doing,Test and find the best way
The PL/SQL runtime engine has two different methods for passing parameter values between stored procedures and functions, by value and by reference.
procedure get_customer_orders ( p_customer_id in number, p_orders out nocopy orders_coll ); theorders orders_coll; get_customer_orders(124, theorders);
If the amount of data to be processed or utilized from your PL/SQL procedure is too large to fit comfortably in a PL/SQL table, use a GLOBAL TEMPORARY table rather than a normal table. A GLOBAL TEMPORARY table has a persistent definition but data is not persistent and the global temporary table generates no redo or rollback information. For example if you are processing a large number of rows, the results of which are not needed when the current session has ended, you should create the table as a temporary table instead: create global temporary table results_temp (...) on commit preserve rows; The on commit preserve rows clause tells the SQL engine that when a transaction is committed the table should not be cleared. The global temporary table will be created in the users temporary tablespace when the procedure populates it with data and the DIRECT_IO_COUNT will be used to govern the IO throughput (this usually defaults to 64 blocks).
The bulk operation takes less than half the time to populate the collection from the query.
FOR i IN l_id_tab.first .. l_id_tab.last LOOP UPDATE forall_test SET id = l_id_tab(i), code = l_code_tab(i), description = l_desc_tab(i) WHERE id = l_id_tab(i); END LOOP; FORALL i IN l_id_tab.first .. l_id_tab.last UPDATE forall_test SET id = l_id_tab(i), code = l_code_tab(i), description = l_desc_tab(i) WHERE id = l_id_tab(i) RETURNING id, description BULK COLLECT INTO l_out_tab;
Rule #6 : Tuning Dynamic SQL with EXECUTE IMMEDIATE and Cursor Variables
v_ename VARCHAR2(15);
v_sal NUMBER := 1000; table_name VARCHAR2(30) := 'employees'; BEGIN
OPEN emp_cv FOR 'SELECT last_name, salary FROM ' || table_name || ' WHERE salary > :s' USING v_sal;
CLOSE emp_cv; END; /
Any Questions ?