How I Tuned an Oracle SQL Query from 240+ Seconds to 0.14 Seconds
Vijendra singh
Performance Engineering Leader | Expertise in Java performance and SQL Tuning | Delivering Scalable, High-Performance Systems | Principal Performance engineer at Oracle
Performance tuning is a fascinating aspect of database management, and I recently encountered an interesting challenge. A query that initially took over 240 seconds to execute was optimized to run in just 0.14 seconds. Here's a detailed breakdown of the journey, the problems identified, and the solutions implemented.
The Query Scenario
The query aimed to fetch specific columns from a combination of multiple joins between views. These views were built on subqueries to calculate arithmetic values like MIN, MAX, and SUM. While the query used indexed columns in its join and filter criteria, two significant issues slowed it down.
The Problems Identified
Problem 1: Overuse of Nested Queries
The query had several nested subqueries in the FROM clause using the ANY operator. A simplified structure of the query is shown below:
SELECT
A.column4 AS "Min",
A.column5 AS "Max",
A.column6 AS "Sum"
FROM (
(SELECT MIN("A13"."EXPIRE_DATE") FROM TableC "A13" WHERE "A13"."Test_ID" = ANY (
SELECT "A14"."Test_ID" FROM TableD "A14" WHERE "A14"."Another_ID" = "A2"."Col00001"
)) AS "EARLIEST_EXPIRE_DATE",
(SELECT MAX("A13"."NEW_DATE") FROM TableC "A13" WHERE "A13"."Test_ID" = ANY (
SELECT "A14"."Test_ID" FROM TableD "A14" WHERE "A14"."Another_ID" = "A2"."Col00001"
)) AS "LATEST_EXPIRE_DATE",
(SELECT SUM(CASE WHEN "A7"."Payment_STATUS" = 'VOID' THEN 0 ELSE "A7"."Payment_AMOUNT" END)
FROM TableE "A7"
WHERE "A7"."Test_ID" = ANY (
SELECT "A20"."Test_ID" FROM TableC "A20" WHERE "A20"."Test_ID" = ANY (
SELECT "A21"."Test_ID" FROM TableD "A21" WHERE "A21"."Another_ID" = "A2"."Col00001"
)
)) AS "TOTAL_Payment_Amount"
FROM (
SELECT "A4"."XYX_ID" AS "Col00001"
FROM TableF "A4", TableG "A3"
WHERE "A3"."XYX_ID" = "A4"."XYX_ID"
) AS "A2"
) AS "A1"
WHERE "A1".Test_ID = :BindValue;
Problem 2: Missing Index on Key Column
Steps Taken to Solve the Performance Bottleneck
Step 1: Generate SQLHC Report
Using Oracle's SQLHC (SQL Health Check) report, I analyzed the query's execution plan. Key findings included:
领英推荐
Step 2: Apply Index on TableD
To address the full table scan on TableD, I created an index on the Another_ID column:
CREATE INDEX IDX_ANOTHER_ID ON TableD (Another_ID);
This reduced the query execution time from 240 seconds to 9 seconds by enabling index scans.
Step 3: Rewrite the Query
The = ANY() clause in the subqueries was replaced with equivalent joins that leveraged indexed columns. The optimized query snippet is shown below:
SELECT
SUM(CASE WHEN "A7"."Payment_STATUS" = 'VOID' THEN 0 ELSE "A7"."Payment_AMOUNT" END) AS "TOTAL_Payment_Amount"
FROM
TableE "A7",
TableC "A20",
TableD "A21"
WHERE
"A7"."Test_ID" = "A20"."Test_ID"
AND "A21"."Test_ID" = "A20"."Test_ID"
AND "A21"."Another_ID" = "A2"."Col00001";
This modification:
Results
Key Learnings
Feel free to share your thoughts or experiences with Oracle SQL optimization in the comments!
Dedicated to Customer Success | Customer Growth | Retention Management | Ensuring Maximum ROI | Exceeding Client Expectations | Driving Cloud Excellence
4 周Wow, that's quite a transformation! From a sluggish 240 seconds to a speedy 0.14 seconds - it's like the query went from a sloth to a cheetah! Your solution on SQL optimization are definitely helpful for those of us who want to avoid a slow database. Thanks for sharing, Vijendra singh ??
Founder and Managing Director at DBAce Technologies Pvt. Ltd | We are specialized in Database Performance Engineering | Data Management & Analytics | Cloud and Web Technology Services | Cyber Security | Talent Services
1 个月Dear Vijendra ..we have decades of experience in Oracle performance engineering. We can connect to share the experience. Best regards, Raj