32 Tips For Oracle SQL Query Writing and Performance Tuning
32 Tips For Oracle SQL Query Writing and Performance Tuning
Tuning
I am working with Oracle SQL from day when I joined IT industry and I have been
fascinated by number of things I have learned about SQL, different databases and its
usage over the years.
In early phase of my career, I learned that writing SQL queries was not just about
writing but writing so it can run efficiently. Performance of SQL queries are critical to
any application that is built to use Oracle and I say Oracle because this blog is
specifically for Oracle SQL.
The following is a list of some tips which can be used as guideline to write and review
custom SQL queries. This is by no means an exhaustive list to get the best tuning results
but can serve as a ready reference to avoid the common pitfalls while working with
Oracle SQL:
1. Do not use the set operator UNION if the objective can be achieved through an
UNION ALL. UNION incurs an extra sort operation which can be avoided.
2. Select ONLY those columns in a query which are required. Extra columns which are
not actually used, incur more I/O on the database and increase network traffic.
3. Do not use the keyword DISTINCT if the objective can be achieved otherwise.
DISTINCT incurs an extra sort operation and therefore slows your queries down.
4. If it is required to use a composite index, try to use the Leading column in the
WHERE clause. Though Index skip scan is possible, it incurs extra cost in creating
virtual indexes and may not be always possible depending on the cardinality of the
leading columns.
5. There should not be any Cartesian product in the query unless there is a definite
requirement to do so. I know this is a silly point but we all have done this mistake at one
point
6. Wherever multiple tables are used, always refer to a column by either using an alias or
using the fully qualified name. Do not leave the guess work for Oracle.
18. Joins to complex views are not recommended, particularly joins from one complex
view to another. Often this results in the entire view being instantiated, and then the
query is run against the view data
19. Querying from a view requires all tables from the view to be accessed for the data to
be returned. If that is not required, then do not use the view. Instead, use the base
table(s), or if necessary, define a new view.
20. While querying on a partitioned table try to use the partition key in the WHERE
clause if possible. This will ensure partition pruning.
21. Consider using the PARALLEL hint (only when additional resources can be
allocated) while accessing large data sets.
22. Avoid doing an ORDER BY on a large data set especially if the response time is
important.
23. Consider changing the OPTIMIZER MODE to FIRST_ROWS(n) if the response time
is important. The default is ALL_ROWS which gives better throughput.
24. Use CASE statements instead of DECODE (especially where nested DECODEs are
involved) because they increase the readability of the query immensely.
25. Do not use HINTS unless the performance gains clear.
26. Check if the statistics for the objects used in the query are up to date. If not, use the
DBMS_STATS package to collect the same.
27. It is always good to understand the data both functionally and its diversity and
volume in order to tune the query. Selectivity (predicate) and Cardinality (skew) factors
have a big impact on query plan. Use of Statistics and Histograms can drive the query
towards a better plan.
28. Read explain plan and try to make largest restriction (filter) as the driving site for
the query, followed by the next largest, this will minimize the time spent on I/O and
execution in subsequent phases of the plan.
29. If Query requires quick response rather than good throughput is the objective, try to
avoid sorts (group by, order by, etc.). For good throughput, optimizer mode should be
set to ALL ROWS.
30. Queries tend to perform worse as they age due to volume increase, structural
changes in the database and application, upgrades etc. Use Automatic Workload