Presentation on theme: "SQL Tuning Briefing Null is not equal to null but null is null."— Presentation transcript:
SQL Tuning Briefing Null is not equal to null but null is null
What are Best Practices ? A set of guiding principles proposed by industry leading experts Acknowledgement that the application is part of an evolving lifecycle which will continue to iterate over a period of time Determination to deliver a quality product or what we used to call taking pride in your work! Objectively and consistently leads to: – better structured, more robust code – more accurate code – better performing code – better maintained code – more readable code Much less reliance on individual developers Repeatability and measurability
Single Developer Best Practices
Development team best practice One-tenth of a second is about the limit for having the user feel that the system is reacting instantaneously Team Developers Process Prepare Write & Compile Test Code Debug Code Review Optimize SQL US Development Team HK Development Team ZHA/SHA Development Team Team Review Scheduled Code Review Benchmark test & SQL Scan Manager Management Reporting Bad Code or Problematic SQL Detected: Return to Development Pre-deployment QA: Regression Testing and Scalability/ Performance Tuning Code Review Successful Production Database Version Control (Team Coding)
Challenges Higher speed means more business Less resource consumption means more concurrent usersProblems The challenges and problems of application A Constantly-changing Environment
What affects performance? n Hardware –Disk space –RAM –Network –CPU n Operating System settings n Database Server parameter settings n Database Design n Indexes on Database Tables n SQL statement
Why SQL statement affecting performance 90% 60%
Performance Problems Application Others According to industrial experts 60% of the databases performance problems are caused by applications
DBMS Optimize - Find the best way to process your SQL Statements Very Good (sometime for simple SQL) Good (Normally, but still be improved) Very Bad (most of time for complex SQL)
Why does SQL need tuning? n It is easy to write functional SQL. n It is harder to write efficient, high performing SQL.
Why is it so hard? n your database structure n how SQL statements work in general n how Database executes SQL n database changes over time You must know Then its trial and error until you get a satisfactory result.
Why dont people tune their SQL? n Too busy now. Ill do it later. n Is that what the Oracle optimizer is for? n Im a Java, not an SQL, programmer. n I dont know how. n Generated by Toplink, not my business. n Its works. Ive got my data. Im happy.
n Generate SQL code based on its own object-oriented functions n Toplink will transform the object-oriented requests into object-liked SQL statements n Relational based SQL engine like Oracle to execute an object-liked SQL statements may cause unprecedented large system resources utilization and bad system performance Top Link problem
When is the best time to tune SQL? At the time it is written As the database changes
Server receives SQL Parses Oracle optimizer determines the execution path Binds variables Executes How does Oracle process SQL?
How Oracle Optimizer works Internal rewrite & generation of multiple execution plans Plan 1 cost=1000 Plan 2 cost=3000 Plan 3 cost=4000 Plan 4 cost= 500 Execution How accurate is the cost estimation? Plan 1 Plan 2 Plan 3 Plan 4 Cost estimation Does it try every possible way to rewrite your SQL? SQL
Limitations of Optimizer n Limited SQL rewrite n Resource limitation n Cost estimation is only an estimation n Problems too complex for optimizer
Basic Concept of SQL Execution - Driving Path SELECT * FROM A, B, C WHERE A.key1 = B.key1 AND B.key2 = C.key2 AND C.f2 = 0 AND A.f1 = 0 Driving Path : CBA
Driving Path : ABC
Why join path matter n Path from table A to table B: which means that we open table A, looking at each row to then use an index to search for matching rows in table B: select * from A, B /* table A has 100,000 records */ where A.key = B.key /* table B has 1,000 records */ Path from BA is around 59 times faster than the speed of AB n Path from table B to table A: which means that we open B table, looking at each row to then use an index to search for matching rows in table A: –Number of Operations (AB) = 100,000 * RoundUp(LN(1000) / LN(2)) / 2 = 100,000 * 10 / 2 = 500,000 –Number of Operations (BA) = 1000 * RoundUp(LN(100,000) / LN(2)) / 2 = 1000 * 17 / 2 = 8,500
Why join path matter n 500,000 operations8500 operations Full Table Scan A B B Index Scan A Index Scan Full Table Scan
Specific Tips for writing SQL
Use table join in place of sub-query If A,B is many to one or one to one relationship Replace Select * from A where A.CITY in (select B.City from B) With Select A.* from A, B where A.CITY = B.CITY
Select the smallest table and/or smallest result set first. SELECT * FROM A,B WHERE A.STATE = CA AND B.CITY =CONCORD Joins
If A is a large table and B is small. Small table should drive the large table. Disable index on B. This changes the table driving path. Replace SELECT * FROM A,B WHERE A.STATE = B.STATE With SELECT * FROM B,A WHERE A.STATE = B.STATE || '' JoinsChange table driving path
For some complex SQL(Group function, Set function), Views SQL is normally cannot be merged to your upper layer SQL. So, Oracle normally processes the view first, creates a temp table which does not have any indexes, and you cannot tune the view because Oracle always handles the view in the same manner. Avoid Views
Explain Plan n Analyze your Explain Plan. n Always test the SQL statement to find its actual time.
Indexed Fields Know your indexes and use them to your advantage.
If you want the index used, dont perform an operation on the field. Replace SELECT * from A where SALARY = :NEWSALARY with SELECT * from A where SALARY = :NEWSALARY Indexed Fields
Index will not be used when a function is used. SELECT * from A where substr(name, 1, 3) = 'Wil' Indexed Fields
WHERE clause Avoid using != (not equal to) Like '%SA%' Indexed Fields
Sometimes DO disable the index SELECT * FROM A WHERE SALARY + 0 = '10000' AND DEPT = 'IT' SELECT * FROM A WHERE EMP_SEX || '' = 'm' Indexed Fields
Do not have default value set to NULL. If it is a number field and lowest value is 0, then: Replace SELECT * FROM A WHERE NUMBER IS NOT NULL with (normally faster response time) SELECT * FROM A WHERE NUMBER >0 Indexed Fields
Index Fields Replace Outer Join with Union. If both A.State and B.State have a unique indexed: Replace SELECT A.CITY, B.CITY FROM A,B WHERE A.STATE=B.STATE(+) With SELECT A.CITY, B.CITY FROM A,B WHERE A.STATE=B.STATE UNION SELECT NULL, B.CITY FROM B WHERE NOT EXISTS (SELECT 'X' FROM A Where A.STATE=B.STATE)
Learn to use optimization hints RuleStar First_RowStar_Transformation All_RowsIndex_Combine OrderedMerge Use_HashNo_Merge Use_Concat No_Expand Parallel Driving_Site Optimization Hints
Use concatenated index. If A table is indexed with lastname, firstname. Replace SELECT * FROM A WHERE lastname = 'Smith' ORDER BY firstname With SELECT * FROM A WHERE lastname = 'Smith' ORDER BY lastname, firstname ORDER BY clause
Assume table A,B relationship is one to many. The following statements have the same results. SELECT * FROM A WHERE A.CITY IN (SELECT B.CITY FROM B) SELECT * FROM A WHERE EXISTS (SELECT CITY FROM B WHERE A.CITY = B.CITY) EXIST and IN Sub-query
Use IN Sub-query n A.CITY is indexed, B.CITY is not indexed, and table B has much less rows than A. SELECT * FROM A WHERE A.CITY IN (SELECT B.CITY FROM B) SELECT * FROM A WHERE A.CITY IN (SELECT B.CITY|| FROM B) n A.CITY is indexed, B.CITY is indexed, and table B has much less rows than A.
Use EXISTS Sub-query n A.CITY is not indexed and B.CITY is indexed, and B has more rows than A. SELECT * FROM A WHERE EXISTS (SELECT CITY FROM B WHERE A.CITY = B.CITY) n A.CITY is indexed and B.CITY is indexed, and table B has more rows than A. SELECT * FROM A WHERE EXISTS (SELECT CITY FROM B WHERE A.CITY|| = B.CITY)
Variables Problem select * from Employee where (Emp_id>:range_lower or :range_lower is null) and (A.key<:range_upper or :range_upper is null) To enable index range search with a input range boundaries. select * from Employee where Emp_id>=nvl(:range_lower,min, Emp_id) and A.key<=nvl(:range_upper, A.key)
Transitivity Select * from A,B,C where A.key=B.key and B.key=C.key and C.key=text To make Oracles optimizer more intelligent by increasing the transitivity(as Oracles Optimizer cannot do very complicated transitivity improvement internally) Select * from A,B,C where A.key=B.key and B.key=C.key and A.key=C.key and C.key=text and A.key=text and B.key=text
select * from A where (A.key1,A.key2) not in (select B.key1,B.key2 from B) select * from A where (A.key1,A.key2) in (select B.key1,B.key2 from B minus select A.key1,A.key2 from A) Complex SQL Transformation Sometimes the following transformation may give you surprise !
Which SQL is best? SQL1 SQL2
select emp_name, dpt_name, grd_desc from employee, department DEPARTMENT1, grade where emp_grade = grd_id and emp_dept = dpt_id and EXISTS (SELECT 'X' from department DEPARTMENT2 WHERE dpt_avg_salary in (select min(dpt_avg_salary) from department DEPARTMENT3) AND dpt_id = EMPLOYEE.emp_dept) How many ways can you rewrite this statement?