Upload
smitha-padmanabhan
View
299
Download
5
Embed Size (px)
Citation preview
Technical Skills Enhancement – PL/SQL Best practices
Objectives
At the end of this training, you will be able to:
• Understand best practices in SQL and PL/SQL
Agenda
– Indexes
– Logical tuning
– Benefits of using exists
– Avoid distinct
– Know your data, know your query
– Check code behind views
PL/SQL Tuning for performance- Indexes
• Indexes help Oracle find rows easily as rowid references are stored in Indexes.
• Similar to reading from a book
Guidelines for creating indexes
• Do create indexes on– Columns frequently used in WHERE clause
– Columns used in joins
• Avoid creating indexes on– Columns whose data is updated frequently
Indexes – not too many, not too few
Create indexes only when it is absolutely necessary. While indexes aid in improving the performance of queries, too many indexes on a table could drastically slow down the inserts and updates to the table.
PL/SQL Tuning for performance- Indexes
Note: Although it is not a standard practice to create indexes on platform tables (starting with SI_), sometimes when performance issues are seen it might require an index to be created. In this case, ensure that care is taken to recreate the indexes after each platform upgrade.
Guidelines for indexes• When creating composite indexes, the order of columns is important. The
column that is more frequently queried must be put first. If the columns have a parent-child relation, then the parent column should come first.
Script : IndexBestPractices.sql
– Missing leading index column in join Can’t use index• Eg: Composite index on STATE, CITY
where state = 'TX' [Index used]
where city = 'DALLAS' [Index Not Used]
where state = 'TX' and city = 'DALLAS' [Index Used]
PL/SQL Tuning for performance- Indexes
– NOT, != and <> disable index use
where state not in ('TX', 'FL','OH')[Index Not used]
where state != 'TX' [Index Not used]
Instead try to use IN or = whenever possible
– NULL value references can never use indexes
where state IS NULL [Index Not used]
where state IS NOT NULL [Index Not used]
– Expression references can never use indexes
where substr(city,1,3) = 'DAL' [Index Not used]
where city like 'DAL%' [Index Used]
where city || state = 'DALLASTX' [Index Not used]
where salary * 12 >= 24000 [Index Not used]
where salary >= 2000 [Index Used]
PL/SQL Tuning for performance- Indexes
• Avoid using functions on table columns in WHERE clause, instead use local variables.
• Functions on indexed columns prevent Index scans, unless there is a function based index on the column.
• DO NOT: “where trunc(created_date) > …”
• BETTER: “where created_date > “
• DO NOT: select * from accounts where account_status = get_system_constants(‘SUSPENDED STATUS’);
• BETTER: l_suspended_status := get_system_constants(‘SUSPENDED STATUS’);
select * from accounts where account_status = l_suspended_status;
PL/SQL Tuning for performance – The benefits of using EXISTS
Lesson Learned
In a query joining multiple tables if some tables are not represented in the SELECT clause (ie : columns from those tables are not in SELECT clause) those tables can be moved from JOIN to EXISTS.
EXISTS is always better than using JOIN(in some cases) or IN. This is because once Oracle finds the first record that fulfills the subquery in the EXISTS clause, it does not bother to check the remaining records.
Consider the below query- SELECT user_nameFROM usersWHERE user_id IN (SELECT user_id FROM user_org_roles)
FOR EACH user_id IN USERS FOR EACH user_id IN USER_ORG_ROLES IF USERS.user_id = USER_ORG_ROLES.user_id THEN TRUE; END IF; END LOOP;END LOOP;
100 users x 1000 org roles = 100,000 comparisons!
PL/SQL Tuning for performance – The benefits of using EXISTS
Rewriting using EXISTSSELECT a.user_nameFROM users aWHERE EXISTS (SELECT b.user_id FROM user_org_roles b WHERE b.user_id = a.user_id)
FOR EACH user_id IN USERS
IF user_id EXISTS in USER_ORG_ROLES THEN
RETURN row;
END IF;
END LOOP;
100 users = 100 comparisons!
PL/SQL Tuning for performance – Avoid DISTINCT
Reqmt : Users in organization 100000
SELECT u.user_id , u.user_nameFROM users u , user_org_roles rWHERE u.user_id = r.user_idAND r.org_id = 100000;USER_ID USER_NAME------------ -------------------------------100001 JOHN DOE100001 JOHN DOE
Lazy developer approach
SELECT DISTINCT u.user_id , u.user_nameFROM users u , user_org_roles rWHERE u.user_id = r.user_idAND r.org_id = 100000;
USER_ID USER_NAME------------ -------------------------------100001 JOHN DOE
PL/SQL Tuning for performance –Avoid DISTINCT
• DISTINCT
– Fetch All Rows satisfying the join
– Sort and Filter duplicate values
– Uses TEMP tablespace if resultset is large
• Better way to fetch unique values using EXISTS
SELECT u.user_id , u.user_nameFROM users uWHERE EXISTS ( SELECT 1 FROM user_org_roles r WHERE u.user_id = r.user_id AND r.org_id = 100000 )
SQL Tuning – HAVING vs WHERE• Use HAVING only to filter on aggregate functions (count, sum, avg etc)
• Use WHERE to filter on table columns
Script : SQLBestPractices.sql
Least Efficient:
The statement below is a syntactically correct statement. It will produce the expected result. However filter is done after all the sorting and counting is complete.
SELECT job, city, state, COUNT(empno) FROM city_data
GROUP BY job, city, state
HAVING job='CLERK';
Correct Usage
SELECT job, city, state, COUNT(empno) FROM city_data
WHERE job='CLERK'
GROUP BY job, city, state;
SQL Tuning – UNION vs UNION ALL• The UNION operation sorts the result set to eliminate duplicate rows
• UNION ALL includes duplicate rows and does not require a sort.
• Unless you require that the duplicate rows be eliminated, or you are certain that the member queries do not produce duplicate data, use UNION ALL
SELECT empno, ename, deptno FROM emp_10
UNION
SELECT empno, ename, deptno FROM emp_20;
--Better performance
SELECT empno, ename, deptno FROM emp_10
UNION ALL
SELECT empno, ename, deptno FROM emp_20;
PL/SQL coding guidelines - General
– Use equality first.
– Use range operators only where equality does not apply.
– Avoid use of negatives in the form of “ != ” or ” NOT”.
– Avoid LIKE pattern matching.
– Try to retrieve specific rows and in small numbers.
– Filter from large tables first to reduce rows joined. Retrieve tables in order from the most highly filtered table downwards; preferably the largest table has the most filtering applied.
– The most highly filtered table is the table having the smallest percentage of its rows retrieved, preferably the largest table.
– Use indexes wherever possible except for very small tables.
– Let the Optimizer do its job.
PL/SQL coding guidelines - General
• Modularize with top-down design; keep executable sections small and easy to read
• Modularize to reduce complexity, make your tasks manageable, and make your resulting code maintainable
• Avoid multiple RETURN statements in executable section, instead save values in variables & return the variable
• Avoid lengthy sections of code, and spaghetti code• Code sections should be self documenting• Avoid any code redundancies
PL/SQL Tuning for performance
• There will always be many ways to write a query or PL/SQL program to fulfill a requirement.
• By applying the above concepts and using iterative methods you can figure out which method yields THE BEST performance.
Thank YouFeedback, Questions, Discussion