Reputation: 303
I am creating a view in an Oracle Database and I have a problem regarding the execution time of the query that builds it. It's quite big a query which brings a lot of rows as results. I use 2 UNION
operators, one UNION
and one UNION ALL
. I know that UNION
is optimized but I want to know if I can do anything to make it even faster.
I've tried changing the order of the SELECT
queries but I find the current order to be the fastest. I've also checked on Oracle Docs
and it recommends changing the UNION ALL
operator to a FULL OUTER JOIN
with NVL
operator.
If you want, check it out at http://www.dba-oracle.com/t_oracle_union.htm it's tip number 7.
SELECT
rp."RatePlanCode",
rsi."ProductCode",
rsi."ProductDescription",
rsi."SPCode",
rsi."SPDescription",
rsi."SNCode",
rsi."SNDescription",
rsi."ZNCode",
rsi."ZNDescription",
rsi."UsageIndicatorShortDesc",
pr."ProductName",
pr."ProductTypeId",
rsm."InternalCode",
(
SELECT
"Description"
FROM
"Attribute"
WHERE
"AttributeId" = rsm."AttributeId"
) "Attribute",
rsm."AttributeId",
rsm."CompareColumnValue" "OldCompareValue",
rec."NewCompareColumn",
rec."Timestamp" "ModificationDate",
'Update' AS "RequiredAction"
FROM
"RaUsageMapping" rsm,
"RatePlan" rp,
"RaUsageRecord" rsi,
"MatrixModificationCheck" rec,
"Product" pr
WHERE
rsm."UsageRecordId" = rsi."UsageRecordId"
AND pr."ProductId" = rec."ProductId"
AND rp."RatePlanId" = rsi."RatePlanId"
AND rsm."InternalCode" = rec."InternalCode"
AND rsm."AttributeId" = rec."AttributeId"
AND rsm."CompareColumnValue" = rec."CompareColumn"
AND rec."NewCompareColumn" IS NOT NULL
AND pr."ProductStatusId" IN (
'2',
'6'
)
UNION
SELECT
rp."RatePlanCode",
rsi."ProductCode",
rsi."ProductDescription",
rsi."SPCode",
rsi."SPDescription",
rsi."SNCode",
rsi."SNDescription",
rsi."ZNCode",
rsi."ZNDescription",
rsi."UsageIndicatorShortDesc",
pr."ProductName",
pr."ProductTypeId",
rsm."InternalCode",
(
SELECT
"Description"
FROM
"Attribute"
WHERE
"AttributeId" = rsm."AttributeId"
) "Attribute",
rsm."AttributeId",
rsm."CompareColumnValue" "OldCompareValue",
rec."NewCompareColumn",
rec."Timestamp" "ModificationDate",
'MTB Row deleted' AS "RequiredAction"
FROM
"RaUsageMapping" rsm,
"RatePlan" rp,
"RaUsageRecord" rsi,
"MatrixModificationCheck" rec,
"Product" pr
WHERE
rsm."UsageRecordId" = rsi."UsageRecordId"
AND pr."ProductId" = rec."ProductId"
AND rp."RatePlanId" = rsi."RatePlanId"
AND rsm."InternalCode" = rec."InternalCode"
AND rsm."AttributeId" = rec."AttributeId"
AND rsm."CompareColumnValue" = rec."CompareColumn"
AND rec."NewCompareColumn" IS NULL
AND pr."ProductStatusId" IN (
'2',
'6'
)
UNION ALL
SELECT
rp."RatePlanCode",
rsi."ProductCode",
rsi."ProductDescription",
rsi."SPCode",
rsi."SPDescription",
rsi."SNCode",
rsi."SNDescription",
rsi."ZNCode",
rsi."ZNDescription",
rsi."UsageIndicatorShortDesc",
pr."ProductName",
pr."ProductTypeId",
rsm."InternalCode",
(
SELECT
"Description"
FROM
"Attribute"
WHERE
"AttributeId" = rsm."AttributeId"
) "Attribute",
rsm."AttributeId",
rsm."CompareColumnValue" "OldCompareValue",
NULL,
NULL,
'Invalid Mapping' AS "RequiredAction"
FROM
"RaUsageMapping" rsm,
"RatePlan" rp,
"RaUsageRecord" rsi,
"Product" pr
WHERE
rsm."UsageRecordId" = rsi."UsageRecordId"
AND rp."RatePlanId" = rsi."RatePlanId"
AND pr."InternalCode" = rsm."InternalCode"
AND pr."ProductStatusId" IN (
'2',
'5',
'6'
)
AND ( rsm."InternalCode",
rsm."AttributeId",
rsm."CompareColumnValue" ) NOT IN (
SELECT
"InternalCode",
"AttributeId",
"CompareColumnValue"
FROM
"MappingCheckCompareValues"
);
Is there any way that I can reduce the elapsed time? Any workarounds are welcome.
Upvotes: 0
Views: 2074
Reputation: 3006
First: You should use ANSI join syntax to make your query more readable and easier to maintain.
To speed up your query you should notice that the first 2 queries only differ in the "NewCompareColumn" is null
or is not null
so you can easily combine them to one query using:
CASE WHEN rec."NewCompareColumn" IS NULL
THEN 'MTB Row deleted'
ELSE 'Update'
END AS "RequiredAction"
So the final result will look like this:
SELECT
rp."RatePlanCode",
rsi."ProductCode",
rsi."ProductDescription",
rsi."SPCode",
rsi."SPDescription",
rsi."SNCode",
rsi."SNDescription",
rsi."ZNCode",
rsi."ZNDescription",
rsi."UsageIndicatorShortDesc",
pr."ProductName",
pr."ProductTypeId",
rsm."InternalCode",
(
SELECT
"Description"
FROM
"Attribute"
WHERE
"AttributeId" = rsm."AttributeId"
) "Attribute",
rsm."AttributeId",
rsm."CompareColumnValue" "OldCompareValue",
rec."NewCompareColumn",
rec."Timestamp" "ModificationDate",
CASE WHEN rec."NewCompareColumn" IS NULL
THEN 'MTB Row deleted'
ELSE 'Update'
END AS "RequiredAction"
FROM "RaUsageRecord" rsi
JOIN "RaUsageMapping" rsm
ON rsm."UsageRecordId" = rsi."UsageRecordId"
JOIN "RatePlan" rp
ON rp."RatePlanId" = rsi."RatePlanId"
JOIN "MatrixModificationCheck" rec
ON rec."InternalCode" = rsm."InternalCode"
AND rec."AttributeId" = rsm."AttributeId"
AND rec."CompareColumn" = rsm."CompareColumnValue"
JOIN "Product" pr
ON pr."ProductId" = rec."ProductId"
AND pr."ProductStatusId" IN ('2','6')
UNION ALL
SELECT
rp."RatePlanCode",
rsi."ProductCode",
rsi."ProductDescription",
rsi."SPCode",
rsi."SPDescription",
rsi."SNCode",
rsi."SNDescription",
rsi."ZNCode",
rsi."ZNDescription",
rsi."UsageIndicatorShortDesc",
pr."ProductName",
pr."ProductTypeId",
rsm."InternalCode",
(
SELECT
"Description"
FROM
"Attribute"
WHERE
"AttributeId" = rsm."AttributeId"
) "Attribute",
rsm."AttributeId",
rsm."CompareColumnValue" "OldCompareValue",
NULL,
NULL,
'Invalid Mapping' AS "RequiredAction"
FROM "RaUsageRecord" rsi
JOIN "RaUsageMapping" rsm
ON rsm."UsageRecordId" = rsi."UsageRecordId"
JOIN "RatePlan" rp
ON rp."RatePlanId" = rsi."RatePlanId"
JOIN "Product" pr
ON pr."InternalCode" = rsm."InternalCode"
AND pr."ProductStatusId" IN ('2','5','6')
WHERE ( rsm."InternalCode",
rsm."AttributeId",
rsm."CompareColumnValue" ) NOT IN (
SELECT
"InternalCode",
"AttributeId",
"CompareColumnValue"
FROM
"MappingCheckCompareValues"
)
As by this you get rid of one union
and a null
-check in the where clause which are both slow operations this might speed up your query a lot.
Upvotes: 3
Reputation: 35910
First obvious suggestion to make optimized query is to remove subqueries and use that table in join.
( -- remove this subquery
SELECT
"Description"
FROM
"Attribute"
WHERE
"AttributeId" = rsm."AttributeId"
) "Attribute",
As an example you can remove above subquery and use Attribute
table in join.
There are total 4 subqueries, remove all and use it in join.
In simple terms, Subqueries are executed one per record so if your query is returning 1 million record then subquery will be executed 1 million times and makes your query slower.
Cheers!!
Upvotes: 1