A SQL query cost at least 10s - sql

There is a SQL query in my project witch cost 10s+ every time.
SELECT * FROM (
SELECT TP.TOPIC_ID, CK.NAME
FROM TD_TOPIC TP
INNER JOIN TD_CIRCLE CK on CK.CIRCLE_ID = TP.CIRCLE_ID AND CK.VALID = 1 AND SYSDATE > CK.EFF_TIME
WHERE
TP.VALID = 1 AND TP.FORWARD_FROM_TOPIC_ID = 0
AND (( TP.TOPIC_TYPE = 1 AND TP.APPROVAL_STATUS = 1) OR TP.TOPIC_TYPE IN (0, 2))
AND (TP.TOPIC_TYPE != 2 OR EXISTS (
SELECT 1 FROM TD_VOTE_TOPIC_CONFIG CFG
WHERE CFG.TOPIC_ID=TP.TOPIC_ID AND SYSDATE > CFG.EFFECT_TIME
))
AND (
EXISTS (
SELECT 1 FROM TD_TOPIC_TAG TG WHERE TG.TOPIC_ID=TP.TOPIC_ID
AND TG.TAG_ID IN (1, 2)
)
OR EXISTS (
SELECT 1 FROM TD_CIRCLE_TAG CTG WHERE CTG.CIRCLE_ID=CK.CIRCLE_ID
AND CTG.TAG_ID IN (1, 2)
)
)
ORDER BY TP.CREATE_TIME DESC
) WHERE ROWNUM<21
This is the query plan. It takes too many time on TABLE FULL ACCESS of TP_TOPIC.
3 -------------------------------------------------------------------------------------------------------------
4 | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
5 -------------------------------------------------------------------------------------------------------------
6 | 0 | SELECT STATEMENT | | 20 | 4560 | 4286 (1)| 00:00:52 |
7 |* 1 | COUNT STOPKEY | | | | | |
8 | 2 | VIEW | | 48986 | 10M| 4286 (1)| 00:00:52 |
9 |* 3 | SORT ORDER BY STOPKEY | | 48986 | 6936K| 4286 (1)| 00:00:52 |
10 | 4 | CONCATENATION | | | | | |
11 |* 5 | FILTER | | | | | |
12 |* 6 | HASH JOIN | | 24516 | 3471K| 2140 (1)| 00:00:26 |
13 |* 7 | TABLE ACCESS FULL | TD_CIRCLE | 415 | 44820 | 11 (0)| 00:00:01 |
14 |* 8 | TABLE ACCESS FULL | TD_TOPIC | 75205 | 2717K| 2128 (1)| 00:00:26 |
15 |* 9 | TABLE ACCESS BY INDEX ROWID| TD_CIRCLE_TAG | 1 | 8 | 2 (0)| 00:00:01 |
16 |* 10 | INDEX RANGE SCAN | IDX_TD_CIRCLE_TAG_TAG_ID | 1 | | 1 (0)| 00:00:01 |
17 |* 11 | TABLE ACCESS BY INDEX ROWID| TD_VOTE_TOPIC_CONFIG | 1 | 13 | 2 (0)| 00:00:01 |
18 |* 12 | INDEX RANGE SCAN | IDX_VTCFG_TOPICID | 1 | | 1 (0)| 00:00:01 |
19 |* 13 | FILTER | | | | | |
20 |* 14 | HASH JOIN | | 24516 | 3471K| 2140 (1)| 00:00:26 |
21 |* 15 | TABLE ACCESS FULL | TD_CIRCLE | 415 | 44820 | 11 (0)| 00:00:01 |
22 |* 16 | TABLE ACCESS FULL | TD_TOPIC | 75205 | 2717K| 2128 (1)| 00:00:26 |
23 |* 17 | TABLE ACCESS BY INDEX ROWID| TD_CIRCLE_TAG | 1 | 8 | 2 (0)| 00:00:01 |
24 |* 18 | INDEX RANGE SCAN | IDX_TD_CIRCLE_TAG_TAG_ID | 1 | | 1 (0)| 00:00:01 |
25 |* 19 | TABLE ACCESS BY INDEX ROWID| TD_TOPIC_TAG | 1 | 8 | 2 (0)| 00:00:01 |
26 |* 20 | INDEX RANGE SCAN | IDX_TD_TOPIC_TAG_TAG_ID | 1 | | 1 (0)| 00:00:01 |
27 |* 21 | TABLE ACCESS BY INDEX ROWID| TD_VOTE_TOPIC_CONFIG | 1 | 13 | 2 (0)| 00:00:01 |
28 |* 22 | INDEX RANGE SCAN | IDX_VTCFG_TOPICID | 1 | | 1 (0)| 00:00:01 |
29 -------------------------------------------------------------------------------------------------------------
Table TD_TOPIC is very large. And I found TABLE ACCESS (FULL) of TD_TOPIC. Maybe it is the problem. But I don't know how to make it access by index yet.

SELECT *
FROM (
SELECT TP.TOPIC_ID,
CK.NAME
FROM TD_TOPIC TP
INNER JOIN TD_CIRCLE CK
ON CK.CIRCLE_ID = TP.CIRCLE_ID
LEFT JOIN TD_VOTE_TOPIC_CONFIG CFG
ON CFG.TOPIC_ID=TP.TOPIC_ID
LEFT JOIN TD_CIRCLE_TAG CTG
ON CTG.CIRCLE_ID=CK.CIRCLE_ID
WHERE TP.VALID = 1
AND TP.FORWARD_FROM_TOPIC_ID = 0
AND CK.VALID = 1
AND CK.EFF_TIME < SYSDATE
AND (
(
TP.TOPIC_TYPE = 1
AND TP.APPROVAL_STATUS = 1
)
OR TP.TOPIC_TYPE IN (0, 2)
)
AND (
TP.TOPIC_TYPE != 2
OR
CFG.EFFECT_TIME < SYSDATE
)
AND (
(
TG.TOPIC_ID IS NOT NULL
AND TG.TAG_ID IN (1, 2)
)
OR
(
CTG.CIRCLE_ID IS NOT NULL
AND CTG.TAG_ID IN (1, 2)
)
)
ORDER BY TP.CREATE_TIME DESC
)
WHERE ROWNUM<21

Related

MAX function is causing performance issue in select clause oracle

We have one query which is causing performance issue because of in select cause in case statement.Without that part,full query completing in 20 sec and with this one query took 3 minutes of time.Any way how we can improve the performance of the select below query
(SELECT MAX (ordered_item)
FROM apps.oe_order_lines_all ool, APPS.MTL_SYSTEM_ITEMS_B b
WHERE ool.ato_line_id = oola.line_id
AND ool.inventory_item_id = b.inventory_item_id
AND ool.ship_from_org_id = b.organization_id
AND b.item_type = 'CONFIGURED_ITEM'
AND ool.FLOW_STATUS_CODE <> 'CANCELLED')
As it is self join with ool and if i remove that join it is taking time
> SELECT
> DISTINCT
> hzp.PARTY_NAME,
> CASE
> WHEN b.item_type = 'ATO'
> THEN
> (SELECT MAX (ordered_item)
> FROM apps.oe_order_lines_all ool, APPS.MTL_SYSTEM_ITEMS_B b
> WHERE ool.ato_line_id = oola.line_id
> AND ool.inventory_item_id = b.inventory_item_id
> AND ool.ship_from_org_id = b.organization_id
> AND b.item_type = 'CONFIGURED_ITEM'
> AND ool.FLOW_STATUS_CODE <> 'CANCELLED')
> ELSE
> NULL
> END
> ato_configured_item FROM APPS.OE_ORDER_HEADERS_ALL ooha,
> APPS.OE_ORDER_LINES_ALL oola,
> APPS.MTL_SYSTEM_ITEMS_B b,
> APPS.MTL_PARAMETERS mp,
> APPS.OE_HOLD_DEFINITIONS ohd,
> APPS.OE_HOLD_SOURCES_ALL ohsa,
> APPS.OE_ORDER_HOLDS_ALL ooha1,
> APPS.FND_USER fu,
> APPS.HZ_CUST_SITE_USES_ALL hzcsu,
> APPS.HZ_CUST_ACCT_SITES_ALL hzcas,
> APPS.HZ_CUST_ACCOUNTS hzca,
> APPS.HZ_PARTIES hzp,-----------
> APPS.HZ_PARTY_SITES hzps WHERE ooha.HEADER_ID = oola.HEADER_ID
> AND ooha.ORG_ID = oola.ORG_ID
> AND oola.INVENTORY_ITEM_ID = b.INVENTORY_ITEM_ID
> AND b.ORGANIZATION_ID = mp.ORGANIZATION_ID
> AND oola.SHIP_FROM_ORG_ID = mp.ORGANIZATION_ID
> AND ooha.HEADER_ID = ooha1.HEADER_ID
> AND oola.LINE_ID = ooha1.LINE_ID
> AND ooha1.HOLD_SOURCE_ID = ohsa.HOLD_SOURCE_ID
> AND ohsa.HOLD_ID = ohd.HOLD_ID
> AND b.CREATED_BY = fu.USER_ID
> AND hzcsu.SITE_USE_ID = ooha.INVOICE_TO_ORG_ID
> AND hzcas.CUST_ACCT_SITE_ID = hzcsu.CUST_ACCT_SITE_ID
> AND hzca.CUST_ACCOUNT_ID = hzcas.CUST_ACCOUNT_ID
> AND hzp.PARTY_ID = hzca.PARTY_ID
> AND hzps.PARTY_SITE_ID = hzcas.PARTY_SITE_ID
> AND oola.ITEM_TYPE_CODE IN ('MODEL', 'STANDARD', NULL) --Configured Items and Parts
> AND ooha1.RELEASED_FLAG IN ('N', NULL) --Active holds only
> AND ooha.org_id IN ('1703') --1703 = Valves
> AND oola.FLOW_STATUS_CODE NOT IN ('CLOSED', 'CANCELLED')
> AND ooha.FLOW_STATUS_CODE NOT IN ('CLOSED', 'CANCELLED')
> AND oola.open_flag IN ('Y', NULL)
> AND mp.ORGANIZATION_CODE IN ('FIM'
> )
Execution plan
We have one query which is causing performance issue because of MAX (ordered_item) in select cause in case statement.Without that part query completing in 20 sec and with this one query took 3 minutes of time.Any way to handle this MAX so performance can improve.
------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | E-Rows |E-Bytes| Cost (%CPU)| E-Time |
------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 197K(100)| |
| 1 | SORT AGGREGATE | | 1 | 62 | | |
| 2 | NESTED LOOPS | | | | | |
| 3 | NESTED LOOPS | | 42 | 2604 | 145 (0)| 00:00:01 |
|* 4 | TABLE ACCESS BY INDEX ROWID | OE_ORDER_LINES_ALL | 42 | 1722 | 19 (0)| 00:00:01 |
|* 5 | INDEX RANGE SCAN | OE_ORDER_LINES_N17 | 45 | | 4 (0)| 00:00:01 |
|* 6 | INDEX UNIQUE SCAN | MTL_SYSTEM_ITEMS_B_U1 | 1 | | 2 (0)| 00:00:01 |
|* 7 | TABLE ACCESS BY INDEX ROWID | MTL_SYSTEM_ITEMS_B | 1 | 21 | 3 (0)| 00:00:01 |
| 8 | SORT AGGREGATE | | 1 | 210 | | |
| 9 | NESTED LOOPS | | 1 | 210 | 11 (0)| 00:00:01 |
| 10 | NESTED LOOPS | | 1 | 162 | 8 (0)| 00:00:01 |
| 11 | NESTED LOOPS | | 1 | 82 | 6 (0)| 00:00:01 |
| 12 | NESTED LOOPS | | 1 | 41 | 5 (0)| 00:00:01 |
|* 13 | INDEX RANGE SCAN | MTL_ITEM_CATEGORIES_U1 | 1 | 22 | 4 (0)| 00:00:01 |
| 14 | TABLE ACCESS BY INDEX ROWID | MTL_CATEGORY_SETS_B | 1 | 19 | 1 (0)| 00:00:01 |
|* 15 | INDEX UNIQUE SCAN | MTL_CATEGORY_SETS_B_U1 | 1 | | 0 (0)| |
|* 16 | TABLE ACCESS BY INDEX ROWID | MTL_CATEGORY_SETS_TL | 1 | 41 | 1 (0)| 00:00:01 |
|* 17 | INDEX UNIQUE SCAN | MTL_CATEGORY_SETS_TL_U1 | 1 | | 0 (0)| |
|* 18 | TABLE ACCESS BY INDEX ROWID | MTL_CATEGORIES_B | 1 | 80 | 2 (0)| 00:00:01 |
|* 19 | INDEX UNIQUE SCAN | MTL_CATEGORIES_B_U1 | 1 | | 1 (0)| 00:00:01 |
|* 20 | INDEX RANGE SCAN | FND_LOOKUP_VALUES_U1 | 1 | 48 | 3 (0)| 00:00:01 |
| 21 | SORT AGGREGATE | | 1 | 210 | | |
| 22 | NESTED LOOPS | | 1 | 210 | 11 (0)| 00:00:01 |
| 23 | NESTED LOOPS | | 1 | 162 | 8 (0)| 00:00:01 |
| 24 | NESTED LOOPS | | 1 | 82 | 6 (0)| 00:00:01 |
| 25 | NESTED LOOPS | | 1 | 41 | 5 (0)| 00:00:01 |
|* 26 | INDEX RANGE SCAN | MTL_ITEM_CATEGORIES_U1 | 1 | 22 | 4 (0)| 00:00:01 |
| 27 | TABLE ACCESS BY INDEX ROWID | MTL_CATEGORY_SETS_B | 1 | 19 | 1 (0)| 00:00:01 |
|* 28 | INDEX UNIQUE SCAN | MTL_CATEGORY_SETS_B_U1 | 1 | | 0 (0)| |
|* 29 | TABLE ACCESS BY INDEX ROWID | MTL_CATEGORY_SETS_TL | 1 | 41 | 1 (0)| 00:00:01 |
|* 30 | INDEX UNIQUE SCAN | MTL_CATEGORY_SETS_TL_U1 | 1 | | 0 (0)| |
|* 31 | TABLE ACCESS BY INDEX ROWID | MTL_CATEGORIES_B | 1 | 80 | 2 (0)| 00:00:01 |
|* 32 | INDEX UNIQUE SCAN | MTL_CATEGORIES_B_U1 | 1 | | 1 (0)| 00:00:01 |
|* 33 | INDEX RANGE SCAN | FND_LOOKUP_VALUES_U1 | 1 | 48 | 3 (0)| 00:00:01 |
| 34 | SORT AGGREGATE | | 1 | 210 | | |
| 35 | NESTED LOOPS | | 1 | 210 | 11 (0)| 00:00:01 |
| 36 | NESTED LOOPS | | 1 | 162 | 8 (0)| 00:00:01 |
| 37 | NESTED LOOPS | | 1 | 82 | 6 (0)| 00:00:01 |
| 38 | NESTED LOOPS | | 1 | 41 | 5 (0)| 00:00:01 |
|* 39 | INDEX RANGE SCAN | MTL_ITEM_CATEGORIES_U1 | 1 | 22 | 4 (0)| 00:00:01 |
| 40 | TABLE ACCESS BY INDEX ROWID | MTL_CATEGORY_SETS_B | 1 | 19 | 1 (0)| 00:00:01 |
|* 41 | INDEX UNIQUE SCAN | MTL_CATEGORY_SETS_B_U1 | 1 | | 0 (0)| |
|* 42 | TABLE ACCESS BY INDEX ROWID | MTL_CATEGORY_SETS_TL | 1 | 41 | 1 (0)| 00:00:01 |
|* 43 | INDEX UNIQUE SCAN | MTL_CATEGORY_SETS_TL_U1 | 1 | | 0 (0)| |
|* 44 | TABLE ACCESS BY INDEX ROWID | MTL_CATEGORIES_B | 1 | 80 | 2 (0)| 00:00:01 |
|* 45 | INDEX UNIQUE SCAN | MTL_CATEGORIES_B_U1 | 1 | | 1 (0)| 00:00:01 |
|* 46 | INDEX RANGE SCAN | FND_LOOKUP_VALUES_U1 | 1 | 48 | 3 (0)| 00:00:01 |
| 47 | HASH UNIQUE | | 1 | 412 | 197K (1)| 00:00:08 |
| 48 | NESTED LOOPS | | | | | |
| 49 | NESTED LOOPS | | 1 | 412 | 197K (1)| 00:00:08 |
| 50 | NESTED LOOPS | | 1 | 374 | 197K (1)| 00:00:08 |
| 51 | NESTED LOOPS | | 1 | 362 | 197K (1)| 00:00:08 |
| 52 | NESTED LOOPS | | 1 | 356 | 197K (1)| 00:00:08 |
| 53 | NESTED LOOPS | | 1 | 337 | 197K (1)| 00:00:08 |
| 54 | NESTED LOOPS | | 1 | 332 | 197K (1)| 00:00:08 |
| 55 | NESTED LOOPS | | 1 | 287 | 197K (1)| 00:00:08 |
| 56 | NESTED LOOPS | | 1 | 266 | 197K (1)| 00:00:08 |
| 57 | NESTED LOOPS | | 1 | 252 | 197K (1)| 00:00:08 |
| 58 | NESTED LOOPS | | 710 | 159K| 195K (1)| 00:00:08 |
| 59 | NESTED LOOPS | | 710 | 124K| 194K (1)| 00:00:08 |
| 60 | NESTED LOOPS | | 40073 | 4461K| 75450 (1)| 00:00:03 |
|* 61 | TABLE ACCESS FULL | MTL_PARAMETERS | 32 | 288 | 20 (0)| 00:00:01 |
| 62 | INLIST ITERATOR | | | | | |
|* 63 | TABLE ACCESS BY INDEX ROWID| OE_ORDER_LINES_ALL | 1252 | 128K| 3362 (1)| 00:00:01 |
|* 64 | INDEX RANGE SCAN | OE_ORDER_LINES_X101 | 10395 | | 161 (1)| 00:00:01 |
| 65 | TABLE ACCESS BY INDEX ROWID | MTL_SYSTEM_ITEMS_B | 1 | 66 | 3 (0)| 00:00:01 |
|* 66 | INDEX UNIQUE SCAN | MTL_SYSTEM_ITEMS_B_U1 | 1 | | 2 (0)| 00:00:01 |
|* 67 | TABLE ACCESS BY INDEX ROWID | OE_ORDER_HEADERS_ALL | 1 | 50 | 2 (0)| 00:00:01 |
|* 68 | INDEX UNIQUE SCAN | OE_ORDER_HEADERS_U1 | 1 | | 1 (0)| 00:00:01 |
|* 69 | TABLE ACCESS BY INDEX ROWID | OE_ORDER_HOLDS_ALL | 1 | 22 | 6 (0)| 00:00:01 |
|* 70 | INDEX RANGE SCAN | OE_ORDER_HOLDS_ALL_N2 | 3 | | 3 (0)| 00:00:01 |
| 71 | TABLE ACCESS BY INDEX ROWID | HZ_CUST_SITE_USES_ALL | 1 | 14 | 3 (0)| 00:00:01 |
|* 72 | INDEX UNIQUE SCAN | HZ_CUST_SITE_USES_U1 | 1 | | 2 (0)| 00:00:01 |
| 73 | TABLE ACCESS BY INDEX ROWID | OE_HOLD_SOURCES_ALL | 1 | 21 | 3 (0)| 00:00:01 |
|* 74 | INDEX UNIQUE SCAN | OE_HOLD_SOURCES_U1 | 1 | | 2 (0)| 00:00:01 |
|* 75 | TABLE ACCESS BY INDEX ROWID | OE_HOLD_DEFINITIONS | 1 | 45 | 1 (0)| 00:00:01 |
|* 76 | INDEX UNIQUE SCAN | OE_HOLDS_U1 | 1 | | 0 (0)| |
|* 77 | INDEX UNIQUE SCAN | FND_USER_U1 | 1 | 5 | 0 (0)| |
| 78 | TABLE ACCESS BY INDEX ROWID | HZ_CUST_ACCT_SITES_ALL | 1 | 19 | 2 (0)| 00:00:01 |
|* 79 | INDEX UNIQUE SCAN | HZ_CUST_ACCT_SITES_U1 | 1 | | 1 (0)| 00:00:01 |
|* 80 | INDEX UNIQUE SCAN | HZ_PARTY_SITES_U1 | 1 | 6 | 1 (0)| 00:00:01 |
|* 81 | INDEX RANGE SCAN | XXAR_HZ_CUST_ACCOUNTS_N2 | 1 | 12 | 2 (0)| 00:00:01 |
|* 82 | INDEX UNIQUE SCAN | HZ_PARTIES_U1 | 1 | | 1 (0)| 00:00:01 |
| 83 | TABLE ACCESS BY INDEX ROWID | HZ_PARTIES | 1 | 38 | 2 (0)| 00:00:01 |
Why not try something like this:
with ord_items as (
SELECT MAX (ordered_item) moi, ool.ato_line_id
FROM apps.oe_order_lines_all ool, APPS.MTL_SYSTEM_ITEMS_B b
WHERE ool.inventory_item_id = b.inventory_item_id
AND ool.ship_from_org_id = b.organization_id
AND b.item_type = 'CONFIGURED_ITEM'
AND ool.FLOW_STATUS_CODE <> 'CANCELLED'
group by ool.ato_line_id)
SELECT
DISTINCT
hzp.PARTY_NAME,
CASE
WHEN b.item_type = 'ATO'
THEN
(select ois.moi from ord_items ois where ois.ato_line_id = oola.line_id)
ELSE
NULL
END
ato_configured_item FROM ....

Oracle Insert SQL Query Performance Tuning

I have an Insert query which is taking around 5-6 minutes to complete I plan to reduce timing to under 1 minutes.
I see a MERGE JOIN CARTESIAN in the explain plan so looking for ways to avoid it.
Below is concerned query and Explain Plan.
DB : Oracle Database 19c Standard Edition 2 Release 19.0.0.0.0 - Production
INSERT INTO dictdm_discounts_perf
(
DISCOUNT_MIGRATION_ID,
DISCOUNT_NAME,
DISCOUNT_LEVEL,
RBM_PRODUCT_ID,
DISCOUNTED_OFFER_MIGR_ID,
DISCOUNTED_FLAT_OFFER_NAME,
DISCOUNTED_OFFERING_ID,
DISCOUNTED_OFFERING_NAME,
APPLY_MODE,
VALID_TO,
VALID_FROM,
DURATION,
DURATION_UNIT,
PRICE_COMPONENT_SPEC_ID,
PRICE_COMPONENT_SPEC_NAME,
ALT_PRICE,
ABSOLUTE_ALTERATION,
ALTERATION_IN_PERCENT,
TARIFF_ID,
DISCOUNT_RULE,
LEGACY_TARIFF_ID,
DISC_GROUP_ID,
DISC_GROUP_NAME
)
select
dsct.DISCOUNT_ID DISCOUNT_MIGRATION_ID
,dsct.NAME DISCOUNT_NAME
,(select lv.value from nc_list_values lv
where lv.list_value_id = DISCOUNT_LEVEL_VALUE_ID) DISCOUNT_LEVEL
,dsct.DISCOUNT_PRODUCT_ID RBM_PRODUCT_ID
,do.OFFER_MIGRATION_ID DISCOUNTED_OFFER_MIGR_ID
,do.FLAT_OFFERING_NAME DISCOUNTED_FLAT_OFFER_NAME
,do.OFFERING_ID DISCOUNTED_OFFERING_ID
,do.OFFERING_NAME DISCOUNTED_OFFERING_NAME
,(select lv.value from nc_list_values lv where lv.list_value_id = dsct.APPLY_MODE_VALUE_ID) APPLY_MODE
,dsct.AVAILABLE_TO VALID_TO
,dsct.AVAILABLE_FROM VALID_FROM
,dsct.DURATION DURATION
,(select lv.value from nc_list_values lv where lv.list_value_id = dsct.DURATION_UNIT_VALUE_ID) DURATION_UNIT
,pa.PRICE_SPEC_ID PRICE_COMPONENT_SPEC_ID
,(select o.name from nc_objects o where o.object_id = pa.PRICE_SPEC_ID) PRICE_COMPONENT_SPEC_NAME
,pa.PRICE_ALTERATION_ID ALT_PRICE
,decode(pa.DISC_AMOUNT_TYPE_VALUE_ID,9154646390213102438/*Absolute*/,pa.DISCOUNT_AMOUNT,null) ABSOLUTE_ALTERATION
,decode(pa.DISC_AMOUNT_TYPE_VALUE_ID,9154646390213102439/*Percentage*/,pa.DISCOUNT_AMOUNT,null) ALTERATION_IN_PERCENT
,pp.EXTERNAL_PRICE_PLAN_ID TARIFF_ID
,rl.RULE_ID DISCOUNT_RULE
,dsct.LEGACY_TARIFF_ID LEGACY_TARIFF_ID
,PD.DISCOUNT_GROUP_ID DISC_GROUP_ID
,O.NAME DISC_GROUP_NAME
from
POC_DISCOUNT dsct
join POC_DISCOUNT_TO_OBJECT d2o on d2o.DISCOUNT_ID = dsct.DISCOUNT_ID
join DICTDM_OFFERINGS do on decode(d2o.TYPE_ID,
9155001372713095116/*Offering*/, do.OFFERING_ID,
9155431485713090836/*Falt Offering*/, do.OFFER_MIGRATION_ID) = d2o.OBJECT_ID
or (d2o.TYPE_ID = 9155001372713095117/*Category*/ and instr(do.OFFERING_CATEGORY_ID,d2o.OBJECT_ID)>0)
left join POC_PRICE_ALTERATION pa on pa.DISCOUNT_ID = dsct.DISCOUNT_ID
left join PRICE_PLAN pp on pp.FLAT_OBJECT_ID = dsct.DISCOUNT_ID and pp.DISCOUNTED_OFFERING_ID = do.OFFERING_ID
left join POC_DISCOUNT_TO_RULE rl on rl.DISCOUNT_ID = dsct.DISCOUNT_ID
left join POC_DISCOUNT_TO_GROUP PD ON dsct.DISCOUNT_ID=PD.DISCOUNT_ID
left join NC_OBJECTS O ON O.OBJECT_ID=PD.DISCOUNT_GROUP_ID
where not exists (
select 0 from nc_params ofst
where ofst.object_id = do.offering_id
and ofst.attr_id = 7021759771013444983 /*Status*/
and ofst.list_value_id = 9140545748713273967 /*Discontinued*/
);
Plan hash value: 3564192537
------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------------------------------------
| 0 | INSERT STATEMENT | | 10987 | 5203K| 4703 (1)| 00:00:01 |
| 1 | LOAD TABLE CONVENTIONAL | DICTDM_DISCOUNTS | | | | |
| 2 | TABLE ACCESS BY INDEX ROWID | NC_LIST_VALUES | 1 | 23 | 1 (0)| 00:00:01 |
|* 3 | INDEX UNIQUE SCAN | XPKNC_LIST_VALUES | 1 | | 1 (0)| 00:00:01 |
| 4 | TABLE ACCESS BY INDEX ROWID | NC_LIST_VALUES | 1 | 23 | 1 (0)| 00:00:01 |
|* 5 | INDEX UNIQUE SCAN | XPKNC_LIST_VALUES | 1 | | 1 (0)| 00:00:01 |
| 6 | TABLE ACCESS BY INDEX ROWID | NC_LIST_VALUES | 1 | 23 | 1 (0)| 00:00:01 |
|* 7 | INDEX UNIQUE SCAN | XPKNC_LIST_VALUES | 1 | | 1 (0)| 00:00:01 |
| 8 | TABLE ACCESS BY INDEX ROWID | NC_OBJECTS | 1 | 32 | 1 (0)| 00:00:01 |
|* 9 | INDEX UNIQUE SCAN | XPKNC_OBJECTS | 1 | | 1 (0)| 00:00:01 |
|* 10 | HASH JOIN RIGHT OUTER | | 10987 | 5203K| 4696 (1)| 00:00:01 |
| 11 | TABLE ACCESS FULL | POC_PRICE_ALTERATION | 48 | 2160 | 3 (0)| 00:00:01 |
|* 12 | HASH JOIN RIGHT OUTER | | 9613 | 4130K| 4693 (1)| 00:00:01 |
| 13 | INDEX FULL SCAN | PK_POC_DISCOUNT_TO_RULE | 9 | 81 | 1 (0)| 00:00:01 |
| 14 | NESTED LOOPS OUTER | | 9176 | 3862K| 4692 (1)| 00:00:01 |
| 15 | NESTED LOOPS OUTER | | 9176 | 3575K| 4691 (1)| 00:00:01 |
|* 16 | HASH JOIN RIGHT OUTER | | 9176 | 3342K| 4690 (1)| 00:00:01 |
| 17 | TABLE ACCESS FULL | PRICE_PLAN | 1 | 39 | 3 (0)| 00:00:01 |
|* 18 | HASH JOIN | | 9176 | 2992K| 4687 (1)| 00:00:01 |
| 19 | TABLE ACCESS FULL | POC_DISCOUNT_TO_OBJECT | 43 | 1032 | 3 (0)| 00:00:01 |
| 20 | MERGE JOIN CARTESIAN | | 132K| 39M| 4683 (1)| 00:00:01 |
| 21 | NESTED LOOPS ANTI | | 3167 | 451K| 385 (0)| 00:00:01 |
| 22 | TABLE ACCESS FULL | DICTDM_OFFERINGS | 5660 | 608K| 102 (0)| 00:00:01 |
|* 23 | TABLE ACCESS BY INDEX ROWID BATCHED| NC_PARAMS | 44 | 1584 | 1 (0)| 00:00:01 |
|* 24 | INDEX RANGE SCAN | XIF12NC_PARAMS | 1 | | 1 (0)| 00:00:01 |
| 25 | BUFFER SORT | | 42 | 6888 | 4682 (1)| 00:00:01 |
| 26 | TABLE ACCESS FULL | POC_DISCOUNT | 42 | 6888 | 1 (0)| 00:00:01 |
| 27 | TABLE ACCESS BY INDEX ROWID BATCHED | POC_DISCOUNT_TO_GROUP | 1 | 26 | 1 (0)| 00:00:01 |
|* 28 | INDEX RANGE SCAN | IDX_DISCOUNT_TO_GROUP_D | 1 | | 1 (0)| 00:00:01 |
| 29 | TABLE ACCESS BY INDEX ROWID | NC_OBJECTS | 1 | 32 | 1 (0)| 00:00:01 |
|* 30 | INDEX UNIQUE SCAN | XPKNC_OBJECTS | 1 | | 1 (0)| 00:00:01 |
------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("LV"."LIST_VALUE_ID"=:B1)
5 - access("LV"."LIST_VALUE_ID"=:B1)
7 - access("LV"."LIST_VALUE_ID"=:B1)
9 - access("O"."OBJECT_ID"=:B1)
10 - access("PA"."DISCOUNT_ID"(+)="DSCT"."DISCOUNT_ID")
12 - access("RL"."DISCOUNT_ID"(+)="DSCT"."DISCOUNT_ID")
16 - access("PP"."DISCOUNTED_OFFERING_ID"(+)="DO"."OFFERING_ID" AND
"PP"."FLAT_OBJECT_ID"(+)="DSCT"."DISCOUNT_ID")
18 - access("D2O"."DISCOUNT_ID"="DSCT"."DISCOUNT_ID")
filter("D2O"."OBJECT_ID"=DECODE("D2O"."TYPE_ID",9155001372713095116,"DO"."OFFERING_ID",915543148571309083
6,"DO"."OFFER_MIGRATION_ID") OR "D2O"."TYPE_ID"=9155001372713095117 AND
INSTR("DO"."OFFERING_CATEGORY_ID",TO_CHAR("D2O"."OBJECT_ID"))>0)
23 - filter("OFST"."LIST_VALUE_ID"=9140545748713273967)
24 - access("OFST"."OBJECT_ID"="DO"."OFFERING_ID" AND "OFST"."ATTR_ID"=7021759771013444983)
28 - access("DSCT"."DISCOUNT_ID"="PD"."DISCOUNT_ID"(+))
30 - access("O"."OBJECT_ID"(+)="PD"."DISCOUNT_GROUP_ID")

Function-Based-Index when using IN subquery

I'm have the following code
WITH T AS(
SELECT SOMETHING
)
SELECT * FROM tab1 t1
LEFT JOIN tab2 t2 on t1.ID = t2 .ID
LEFT JOIN tab3 t3 on t1.ID = t3 .ID
LEFT JOIN tab4 t4 on t1.ID = t4.ID
LEFT JOIN tab5 t5 on t1.ID = t5.ID
INNER JOIN tempo_tab6 t6 on t1.ID = t6.ID
LEFT JOIN tab7 t7 on t1.ID = t7.ID
WHERE t1.Col1 = 0
AND t1.Col2 = 1
AND t1.Col3 IN (SELECT t8.Col FROM tab8 t8 WHERE Col ='ABC')
When I execute the Advisor, It advised me create FBI in ID.Col3, but my company rule isn't accept FBI In any case. Is there any way to solve this? It took 18s for some values without Index.
Many thanks.
Edit: this is the execution plan of this case.
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 1976489795
-----------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 873 | 11730 (1)| 00:00:01 |
| 1 | TEMP TABLE TRANSFORMATION | | | | | |
| 2 | LOAD AS SELECT | SYS_TEMP_1FD9EE041_D91A3E0 | | | | |
| 3 | HASH UNIQUE | | 1 | 436 | 15 (7)| 00:00:01 |
| 4 | MERGE JOIN CARTESIAN | | 1 | 436 | 14 (0)| 00:00:01 |
|* 5 | HASH JOIN OUTER | | 1 | 436 | 5 (0)| 00:00:01 |
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------------------------------------------------
| 6 | NESTED LOOPS | | 1 | 220 | 3 (0)| 00:00:01 |
| 7 | NESTED LOOPS | | 1 | 217 | 3 (0)| 00:00:01 |
| 8 | NESTED LOOPS | | 1 | 209 | 2 (0)| 00:00:01 |
|* 9 | TABLE ACCESS FULL | TMP_REPORT | 1 | 204 | 2 (0)| 00:00:01 |
|* 10 | INDEX UNIQUE SCAN | PK_STOCK_ID | 1 | 5 | 0 (0)| 00:00:01 |
|* 11 | INDEX RANGE SCAN | IX_LS_STOCK_ZONE_FK_STOCK_ID_FK_ZONE_ID | 1 | 8 | 1 (0)| 00:00:01 |
|* 12 | INDEX UNIQUE SCAN | PK_ZONE_ID | 1 | 3 | 0 (0)| 00:00:01 |
|* 13 | TABLE ACCESS FULL | TMP_REPORT | 1 | 216 | 2 (0)| 00:00:01 |
| 14 | BUFFER SORT | | 12727 | | 12 (0)| 00:00:01 |
| 15 | INDEX FAST FULL SCAN | PK_STOCK_DEPARTMENT_ID | 12727 | | 9 (0)| 00:00:01 |
| 16 | COUNT | | | | | |
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------------------------------------------------
|* 17 | HASH JOIN SEMI | | 1 | 873 | 11715 (1)| 00:00:01 |
| 18 | MERGE JOIN OUTER | | 1 | 669 | 11713 (1)| 00:00:01 |
| 19 | NESTED LOOPS OUTER | | 1 | 354 | 11709 (1)| 00:00:01 |
| 20 | NESTED LOOPS OUTER | | 1 | 284 | 11708 (1)| 00:00:01 |
| 21 | NESTED LOOPS OUTER | | 1 | 264 | 11707 (1)| 00:00:01 |
| 22 | NESTED LOOPS OUTER | | 1 | 237 | 11706 (1)| 00:00:01 |
| 23 | NESTED LOOPS OUTER | | 1 | 180 | 11705 (1)| 00:00:01 |
| 24 | NESTED LOOPS OUTER | | 1 | 166 | 11704 (1)| 00:00:01 |
| 25 | NESTED LOOPS OUTER | | 1 | 141 | 11703 (1)| 00:00:01 |
| 26 | NESTED LOOPS OUTER | | 1 | 123 | 11702 (1)| 00:00:01 |
|* 27 | HASH JOIN | | 1 | 100 | 11701 (1)| 00:00:01 |
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------------------------------------------------
| 28 | VIEW | | 1 | 26 | 2 (0)| 00:00:01 |
| 29 | TABLE ACCESS FULL | SYS_TEMP_1FD9EE041_D91A3E0 | 1 | 18 | 2 (0)| 00:00:01 |
|* 30 | TABLE ACCESS FULL | LS_ITEM_DETAILS | 870K| 61M| 11696 (1)| 00:00:01 |
| 31 | TABLE ACCESS BY INDEX ROWID| LS_ZONES | 1 | 23 | 1 (0)| 00:00:01 |
|* 32 | INDEX UNIQUE SCAN | PK_ZONE_ID | 1 | | 0 (0)| 00:00:01 |
| 33 | TABLE ACCESS BY INDEX ROWID | LS_INCIDENTS | 1 | 18 | 1 (0)| 00:00:01 |
|* 34 | INDEX UNIQUE SCAN | PK_INCIDENT_ID | 1 | | 0 (0)| 00:00:01 |
| 35 | TABLE ACCESS BY INDEX ROWID | LS_EMPLOYEES | 1 | 25 | 1 (0)| 00:00:01 |
|* 36 | INDEX UNIQUE SCAN | PK_EMPLOYEE_ID | 1 | | 0 (0)| 00:00:01 |
| 37 | TABLE ACCESS BY INDEX ROWID | LS_PROJECTS | 1 | 14 | 1 (0)| 00:00:01 |
|* 38 | INDEX UNIQUE SCAN | PK_PROJECT_ID | 1 | | 0 (0)| 00:00:01 |
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------------------------------------------------
| 39 | TABLE ACCESS BY INDEX ROWID | LS_STOCKS | 1 | 57 | 1 (0)| 00:00:01 |
|* 40 | INDEX UNIQUE SCAN | PK_STOCK_ID | 1 | | 0 (0)| 00:00:01 |
| 41 | TABLE ACCESS BY INDEX ROWID | LS_PLANS | 1 | 27 | 1 (0)| 00:00:01 |
|* 42 | INDEX UNIQUE SCAN | PK_PLAN_ID | 1 | | 0 (0)| 00:00:01 |
| 43 | TABLE ACCESS BY INDEX ROWID | LS_GROUPS | 1 | 20 | 1 (0)| 00:00:01 |
|* 44 | INDEX UNIQUE SCAN | PK_GROUP_ID | 1 | | 0 (0)| 00:00:01 |
| 45 | TABLE ACCESS BY INDEX ROWID | LS_ITEMS | 1 | 70 | 1 (0)| 00:00:01 |
|* 46 | INDEX UNIQUE SCAN | ITEM_CODE_UNI | 1 | | 0 (0)| 00:00:01 |
| 47 | BUFFER SORT | | 2 | 630 | 11712 (1)| 00:00:01 |
| 48 | VIEW | VW_LAT_B17BD126 | 2 | 630 | 4 (0)| 00:00:01 |
| 49 | VIEW | VW_ORE_F374A3FE | 2 | 630 | 4 (0)| 00:00:01 |
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------------------------------------------------
| 50 | UNION-ALL | | | | | |
|* 51 | FILTER | | | | | |
| 52 | TABLE ACCESS BY INDEX ROWID | LS_SUPPLIERS | 1 | 51 | 2 (0)| 00:00:01 |
|* 53 | INDEX UNIQUE SCAN | PK_SUPPLIER_ID | 1 | | 1 (0)| 00:00:01 |
|* 54 | FILTER | | | | | |
| 55 | TABLE ACCESS BY INDEX ROWID | LS_SUPPLIERS | 1 | 51 | 2 (0)| 00:00:01 |
|* 56 | INDEX UNIQUE SCAN | PK_SUPPLIER_ID | 1 | | 1 (0)| 00:00:01 |
|* 57 | TABLE ACCESS FULL | TMP_REPORT | 1 | 204 | 2 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------------------------------------------
The advisor suggest me create this FBI:
create index ISCHN.IDX$$_25380001 on ISCHN.LS_ITEM_DETAILS(SYS_OP_C2C("SERIAL"));

Optimising SQL query using views (& indexes)

I'm having a hard time optimising a sql query that takes about 1 min to complete. Here is the query :
SELECT mpg.ID_PROD_GARN, mpg.NO_PROD
FROM ACO.prime p
JOIN ACO.facture_compt fc
ON fc.id_factr = p.id_factr
JOIN ACO.V_CONTRAT vc
ON vc.NO_POLC = p.NO_POLC
JOIN ACO.MV_PRODUIT mp
ON mp.NO_PROD =vc.NO_PROD
JOIN ACO.MV_PROD_GARN mpg
ON mpg.NO_PROD = mp.NO_PROD
WHERE p.id_prime =
( SELECT MAX(id_prime) AS prime FROM ACO.prime p WHERE p.no_polc='T3167978')
AND mpg.ID_PROD_GARN = '1238'
AND fc.cd_stat_factr = 'comp';
V_CONTRAT is a view and (if my understanding is correct) when joining the view in this way SQL is running trough all the rows to find the result. I did a bit of research and found that indexing this view could speed up my query. So :
CREATE INDEX indx_no_produit ON ACO.V_CONTRAT(NO_PROD);
Unfortunately I get an error saying that I can't index a view SQL : ORA-01702 : you can't use that here.
*Cause: Among other possible causes, this message will be produced if an
attempt was made to define an Editioning View over a view.
*Action: An Editioning View may only be created over a base table.
So my question is how could I speed up this query elegantly?
Many thanks in advance!
Edit 1 : here is the explained plan
Plan hash value: 3107129748
-------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 102 | | 543K (1)| 00:00:22 |
| 1 | NESTED LOOPS | | 1 | 102 | | 543K (1)| 00:00:22 |
| 2 | NESTED LOOPS | | 1 | 90 | | 543K (1)| 00:00:22 |
| 3 | NESTED LOOPS | | 1 | 35 | | 3 (0)| 00:00:01 |
| 4 | NESTED LOOPS | | 1 | 14 | | 2 (0)| 00:00:01 |
| 5 | MAT_VIEW ACCESS BY INDEX ROWID| MV_PROD_GARN | 1 | 9 | | 1 (0)| 00:00:01 |
|* 6 | INDEX UNIQUE SCAN | PK_PROG | 1 | | | 1 (0)| 00:00:01 |
| 7 | BITMAP CONVERSION TO ROWIDS | | 1 | 5 | | 1 (0)| 00:00:01 |
|* 8 | BITMAP INDEX FAST FULL SCAN | MV_PROD_NO_PROD_IDX | | | | | |
| 9 | TABLE ACCESS BY INDEX ROWID | PRIME | 1 | 21 | | 1 (0)| 00:00:01 |
|* 10 | INDEX UNIQUE SCAN | PK_PRIME | 1 | | | 1 (0)| 00:00:01 |
| 11 | SORT AGGREGATE | | 1 | 15 | | | |
| 12 | FIRST ROW | | 1 | 15 | | 1 (0)| 00:00:01 |
|* 13 | INDEX RANGE SCAN (MIN/MAX) | PRIME_NO_POLC_IDX | 1 | 15 | | 1 (0)| 00:00:01 |
|* 14 | VIEW | V_CONTRAT | 1 | 55 | | 543K (1)| 00:00:22 |
| 15 | SORT UNIQUE | | 16M| 5011M| 2740M| 543K (1)| 00:00:22 |
| 16 | UNION-ALL | | | | | | |
|* 17 | HASH JOIN | | 16M| 2502M| | 55963 (4)| 00:00:03 |
| 18 | VIEW | index$_join$_016 | 103 | 1339 | | 2 (0)| 00:00:01 |
|* 19 | HASH JOIN | | | | | | |
| 20 | INDEX FAST FULL SCAN | PK_PROD | 103 | 1339 | | 1 (0)| 00:00:01 |
| 21 | INDEX FAST FULL SCAN | PRODUIT_COMBINE_IDX | 103 | 1339 | | 1 (0)| 00:00:01 |
|* 22 | HASH JOIN RIGHT OUTER | | 16M| 2293M| 261M| 55860 (4)| 00:00:03 |
| 23 | INDEX FAST FULL SCAN | ROL_INDEX1 | 10M| 145M| | 5703 (2)| 00:00:01 |
|* 24 | HASH JOIN RIGHT OUTER | | 6751K| 824M| 117M| 44540 (4)| 00:00:02 |
| 25 | INLIST ITERATOR | | | | | | |
|* 26 | INDEX RANGE SCAN | ROL_CDROL_NOINTR_IDX | 3975K| 72M| | 756 (2)| 00:00:01 |
|* 27 | HASH JOIN RIGHT OUTER | | 4192K| 435M| 90M| 40898 (3)| 00:00:02 |
|* 28 | TABLE ACCESS FULL | ROLE | 2881K| 57M| | 14553 (4)| 00:00:01 |
|* 29 | HASH JOIN | | 2941K| 246M| 104M| 24558 (3)| 00:00:01 |
| 30 | INDEX FAST FULL SCAN | INFO_BASE_DISTRIBUTEUR_FK1 | 4047K| 57M| | 1925 (2)| 00:00:01 |
|* 31 | HASH JOIN | | 2961K| 206M| 136M| 20967 (3)| 00:00:01 |
| 32 | TABLE ACCESS FULL | CONTRAT_ITER | 4088K| 89M| | 12159 (2)| 00:00:01 |
|* 33 | HASH JOIN RIGHT OUTER | | 2961K| 141M| 32M| 7292 (3)| 00:00:01 |
|* 34 | INDEX RANGE SCAN | ROL_CDROL_NOINTR_IDX | 933K| 22M| | 890 (1)| 00:00:01 |
|* 35 | TABLE ACCESS FULL | CONTRAT | 2615K| 62M| | 5781 (3)| 00:00:01 |
|* 36 | HASH JOIN OUTER | | 29239 | 2912K| | 10228 (3)| 00:00:01 |
|* 37 | HASH JOIN | | 29239 | 1941K| | 285 (2)| 00:00:01 |
| 38 | TABLE ACCESS FULL | DISTRIBUTEUR | 9142 | 91420 | | 45 (3)| 00:00:01 |
|* 39 | HASH JOIN | | 29239 | 1656K| | 240 (1)| 00:00:01 |
| 40 | INDEX FULL SCAN | PRODUIT_COMBINE_IDX | 103 | 1030 | | 1 (0)| 00:00:01 |
|* 41 | TABLE ACCESS FULL | TPA_CONTRAT_MENSUEL | 29239 | 1370K| | 239 (1)| 00:00:01 |
| 42 | TABLE ACCESS FULL | COUNTERPARTY | 3547K| 115M| | 9921 (2)| 00:00:01 |
|* 43 | INDEX RANGE SCAN | FACTURE_COMPT_INDEX9 | 1 | 12 | | 1 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
6 - access("MPG"."ID_PROD_GARN"=1238)
8 - filter("MPG"."NO_PROD"="MP"."NO_PROD")
10 - access("P"."ID_PRIME"= (SELECT MAX("ID_PRIME") FROM "ACO"."PRIME" "P" WHERE "P"."NO_POLC"='T3167978'))
13 - access("P"."NO_POLC"='T3167978')
14 - filter("VC"."NO_POLC"="P"."NO_POLC" AND "MP"."NO_PROD"="VC"."NO_PROD")
17 - access("PROD"."NO_PROD"="ITER"."NO_PROD" AND "PROD"."NO_VERS_PROD"="ITER"."NO_VERS_PROD")
19 - access(ROWID=ROWID)
22 - access("ROLAUTRE"."ID_CONT"(+)="CONT"."ID_CONT" AND "ROLAUTRE"."NO_ITER_CONT"(+)="CONT"."NO_DERN_ITER")
24 - access("ROLA"."ID_CONT"(+)="CONT"."ID_CONT" AND "ROLA"."NO_ITER_CONT"(+)="CONT"."NO_DERN_ITER")
26 - access("ROLA"."CD_ROLE"(+)='ap' OR "ROLA"."CD_ROLE"(+)='debit' OR "ROLA"."CD_ROLE"(+)='emprun')
27 - access("ROLPAY"."ID_CONT"(+)="CONT"."ID_CONT" AND "ROLPAY"."NO_ITER_CONT"(+)="CONT"."NO_DERN_ITER")
28 - filter("ROLPAY"."CD_ROLE"(+)='pay' AND "ROLPAY"."IND_PAY_PRI"(+)='1')
29 - access("ITER"."ID_INFO_BASE"="IB"."ID_INFO_BASE" AND "ITER"."NO_ITER_CONT"="IB"."NO_ITER_CONT" AND
SYS_OP_DESCEND("ITER"."NO_ITER_CONT")=SYS_OP_DESCEND("IB"."NO_ITER_CONT"))
31 - access("ITER"."ID_CONT"="CONT"."ID_CONT" AND "ITER"."NO_ITER_CONT"="CONT"."NO_DERN_ITER" AND
SYS_OP_DESCEND("ITER"."NO_ITER_CONT")=SYS_OP_DESCEND("CONT"."NO_DERN_ITER"))
33 - access("ROLP"."ID_CONT"(+)="CONT"."ID_CONT" AND "ROLP"."NO_ITER_CONT"(+)="CONT"."NO_DERN_ITER")
34 - access("ROLP"."CD_ROLE"(+)='pren')
35 - filter("CONT"."NO_SEQ_PROPO_SEL"=0)
36 - access("CTRPY"."LAST_NAME"(+)="TCM"."CON_NOM_ASS_PRINC" AND
"CTRPY"."FRST_NAME"(+)="TCM"."CON_PRENOM_ASS_PRINC" AND "CTRPY"."DT_BIRTH"(+)="TCM"."CON_DATE_NAISS_ASS_PRINC")
37 - access("TCM"."CON_NO_DISTRIBUTEUR"="A"."NO_DIST")
39 - access("PROD"."NO_PROD"="TCM"."CON_CODE_PRODDUIT")
41 - filter("TCM"."CON_VERSION_CONTRAT"=1)
43 - access("FC"."ID_FACTR"="P"."ID_FACTR" AND "FC"."CD_STAT_FACTR"='comp')
Edit 2 : Here is the view V_CONTRAT
SELECT DISTINCT cont.ID_CONT,
cont.NO_POLC,
cont.cd_divs,
prod.no_prod,
prod.cd_cie_encai,
prod.cd_faml_cptb,
ib.no_dist_init,
CASE
WHEN ROLP.ID_ROLE IS NOT NULL THEN ROLP.NO_INTR
WHEN rola.no_intr IS NOT NULL THEN rola.no_intr
WHEN rolpay.no_intr IS NOT NULL THEN rolpay.no_intr
ELSE rolAutre.no_intr
END
AS NO_INTR_PRINC,
rolpay.no_intr AS NO_INTR_PAY
FROM VIRAGE.CONTRAT CONT
INNER JOIN
VIRAGE.contrat_iter iter
ON iter.id_cont = cont.id_cont
AND ITER.NO_ITER_CONT = CONT.NO_DERN_ITER
AND CONT.NO_SEQ_PROPO_SEL = 0
INNER JOIN
VIRAGE.info_base ib
ON iter.id_info_base = ib.id_info_base
AND iter.no_iter_cont = ib.no_iter_cont
INNER JOIN
VIRAGE.produit prod
ON prod.no_prod = iter.no_prod
AND prod.no_vers_prod = iter.no_vers_prod
LEFT JOIN
VIRAGE.role rolp
ON rolp.id_cont = cont.id_cont
AND rolp.no_iter_cont = cont.no_dern_iter
AND rolp.cd_role = 'pren'
LEFT JOIN
VIRAGE.role rola
ON rola.id_cont = cont.id_cont
AND rola.no_iter_cont = cont.no_dern_iter
AND ( rola.cd_role = 'ap'
OR ROLA.CD_ROLE = 'debit'
OR rola.cd_role = 'emprun')
LEFT JOIN
VIRAGE.role rolpay
ON rolpay.id_cont = cont.id_cont
AND rolpay.no_iter_cont = cont.no_dern_iter
AND rolpay.cd_role = 'pay'
AND rolpay.ind_pay_pri = '1'
LEFT JOIN
VIRAGE.role rolAutre
ON rolAutre.id_cont = cont.id_cont
AND rolAutre.no_iter_cont = cont.no_dern_iter
UNION
SELECT DISTINCT
CAST (tcm.con_sequence AS NUMBER (10, 0)) AS id_cont,
CAST (tcm.con_numero_contrat AS VARCHAR2 (20)) AS no_polc,
CAST (vd.cd_divs_compt AS VARCHAR2 (11)) AS cd_divs,
CAST (tcm.con_code_prodduit AS NUMBER (5, 0)) AS no_prod,
CAST (prod.cd_cie_encai AS VARCHAR2 (1)) AS cd_cie_encai,
CAST (prod.cd_faml_cptb AS VARCHAR2 (11)) AS cd_faml_cptb,
CAST (tcm.con_no_distributeur AS VARCHAR2 (15)) AS no_dist_init,
CAST (ctrpy.no_ctrpy AS NUMBER) AS no_intr_princ,
CAST (ctrpy.no_ctrpy AS NUMBER) AS no_intr_pay
FROM TPA.TPA_CONTRAT_MENSUEL tcm
INNER JOIN
VIRAGE.produit prod
ON prod.no_prod = tcm.con_code_prodduit
LEFT JOIN
counterparty ctrpy
ON ctrpy.last_name = tcm.con_nom_ass_princ
AND ctrpy.frst_name = tcm.con_prenom_ass_princ
AND ctrpy.dt_birth = tcm.con_date_naiss_ass_princ
INNER JOIN
v_distributeur vd
ON tcm.con_no_distributeur = vd.no_dist
WHERE TCM.CON_VERSION_CONTRAT=1
Indexes can only be created in tables.
Make sure you create an index for every single foreign key in every table. Oracle does not create them by default as other systems do.
Check also the performance of the sub-query and if it takes too long you should also create indexes for every attribute in the WHERE clause.
Don't forget that indexes need maintenance.

How do I improve the following SQL that has self-join

After doing a select, I am doing a self-join and a distinct on the data. I am not sure if there is a better way to write this query. Could you suggest?
Below is the Query, and the explain plan output.
WITH data
AS ( SELECT san.S1FK_C_ID,
san.S1FK_CF_ID,
san.S1FK_A_ID,
san.S1FK_A_TYPE,
san.S1FK_S_TYPE,
san.S1FK_B_FUNC,
AU.AS1FK_A_ID,
AU.AS1FK_B_FUNC,
AU.AS1FK_S_TYPE,
AU.AS1FK_T_CODE,
A2FK_B_ID,
A2FK_NBR,
A2FK_C_CD,
A1FK_B_ID,
A1FK_NBR,
A1FK_C_CD,
AU.R_NAME,
IND
FROM N_RULE cnr,
SAN san,
ACCT_USG AU
WHERE AU.R_NAME = CNR.R_NAME
AND AU.A2FK_C_CD = CNR.C_CD
AND AU.AS1FK_B_FUNC = CNR.B_FUNC
AND AU.AS1FK_A_ID = san.AS1FK_ID || ''
AND AU.AS1FK_B_FUNC = san.AS1FK_B_FUNC
AND AU.AS1FK_S_TYPE = san.AS1FK_S_TYPE
AND AU.AS1FK_T_CODE = san.AS1FK_A_TYPE
AND CNR.FM_CODE = 'SP'
AND san.STATUS = 'A'
AND san.AS1FK_B_FUNC = CNR.B_FUNC
ORDER BY AU.AS1FK_A_ID)
SELECT DISTINCT A.A2FK_C_CD AS C_CD,
-- secondary id's
B.S1FK_C_ID AS C_ID_2,
B.S1FK_CF_ID AS CF_ID_2,
B.S1FK_A_ID AS A_ID_2,
B.S1FK_B_FUNC AS B_FUNC_2,
B.S1FK_S_TYPE AS S_TYPE_2,
B.S1FK_A_TYPE AS A_TYPE_2,
--primary id's
A.S1FK_A_ID AS A_ID_1,
A.S1FK_B_FUNC AS B_FUNC_1,
A.S1FK_S_TYPE AS S_TYPE_1,
A.S1FK_A_TYPE AS A_TYPE_1
FROM data A, --A is the set of primary and standalone id's
data B
--B is the primary and secondary id's
WHERE
B .R_NAME = A.R_NAME
--as join
AND B.AS1FK_B_FUNC = A.AS1FK_B_FUNC
AND B.AS1FK_S_TYPE = A.AS1FK_S_TYPE
AND B.AS1FK_T_CODE = A.AS1FK_T_CODE
--accts join
AND B.A2FK_NBR = A.A2FK_NBR
AND B.A2FK_B_ID = A.A2FK_B_ID
AND B.A2FK_C_CD = A.A2FK_C_CD
AND B.A1FK_NBR = A.A1FK_NBR
AND B.A1FK_B_ID = A.A1FK_B_ID
AND B.A1FK_C_CD = A.A1FK_C_CD
--s fk join
AND B.S1FK_C_ID = A.S1FK_C_ID
AND B.S1FK_CF_ID = A.S1FK_CF_ID
AND B.S1FK_S_TYPE = A.S1FK_S_TYPE
AND B.S1FK_B_FUNC = A.S1FK_B_FUNC
AND B.S1FK_A_TYPE = A.S1FK_A_TYPE
AND ( --join secondary ( N ) and primary id's ( Y ) to primary id's
( 'Y' = A.IND
AND B.IND IN ('N', 'Y') )
OR --join standalone ( ' ' ) id's to themselves
( ' ' = B.IND
AND ' ' = A.IND )
AND B.AS1FK_A_ID = A.AS1FK_A_ID
);
Plan:
PLAN_TABLE_OUTPUT
Plan hash value: 3120521488
----------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 450 | 18 (17)| 00:00:01 |
| 1 | TEMP TABLE TRANSFORMATION | | | | | |
| 2 | LOAD AS SELECT | SYS_TEMP_0FD9D949F_E879D9BC | | | | |
| 3 | SORT ORDER BY | | 1 | 296 | 12 (9)| 00:00:01 |
| 4 | NESTED LOOPS | | 1 | 296 | 11 (0)| 00:00:01 |
| 5 | NESTED LOOPS | | 7412 | 1889K| 11 (0)| 00:00:01 |
|* 6 | TABLE ACCESS FULL | SAN | 255 | 20910 | 11 (0)| 00:00:01 |
| 7 | TABLE ACCESS BY INDEX ROWID| ACCT_USG | 29 | 5191 | 0 (0)| 00:00:01 |
|* 8 | INDEX RANGE SCAN | ACCT_USG_PK | 1 | | 0 (0)| 00:00:01 |
|* 9 | INDEX UNIQUE SCAN | N_RULE_PK | 1 | 35 | 0 (0)| 00:00:01 |
| 10 | HASH UNIQUE | | 1 | 450 | 6 (34)| 00:00:01 |
|* 11 | HASH JOIN | | 1 | 450 | 5 (20)| 00:00:01 |
| 12 | VIEW | | 1 | 225 | 2 (0)| 00:00:01 |
| 13 | TABLE ACCESS FULL | SYS_TEMP_0FD9D949F_E879D9BC | 1 | 225 | 2 (0)| 00:00:01 |
| 14 | VIEW | | 1 | 225 | 2 (0)| 00:00:01 |
| 15 | TABLE ACCESS FULL | SYS_TEMP_0FD9D949F_E879D9BC | 1 | 225 | 2 (0)| 00:00:01 |
----------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
6 - filter("SAN"."EFF_STATUS_CODE"='A')
8 - access("AU"."AS1FK_A_ID"="SAN"."AS1FK_ID"||'' AND
"AU"."AS1FK_T_CODE"="SAN"."AS1FK_A_TYPE" AND
"AU"."AS1FK_S_TYPE"="SAN"."AS1FK_S_TYPE" AND
"AU"."AS1FK_B_FUNC"="SAN"."AS1FK_B_FUNC")
9 - access("CNR"."FM_CODE"='SP' AND "SAN"."S1FK_C_ID"="CNR"."CLRG_ORG_ID" AND
"SAN"."AS1FK_B_FUNC"="CNR"."B_F_CODE" AND "AU"."A2FK_C_CD"="CNR"."C_CD" AND
"AU"."R_NAME"="CNR"."R_NAME")
filter("AU"."AS1FK_B_FUNC"="CNR"."B_F_CODE")
11 - access("B"."R_NAME"="A"."R_NAME" AND "B"."AS1FK_B_FUNC"="A"."AS1FK_B_FUNC" AND
"B"."AS1FK_S_TYPE"="A"."AS1FK_S_TYPE" AND "B"."AS1FK_T_CODE"="A"."AS1FK_T_CODE"
AND "B"."A2FK_NBR"="A"."A2FK_NBR" AND "B"."A2FK_B_ID"="A"."A2FK_B_ID" AND
"B"."A2FK_C_CD"="A"."A2FK_C_CD" AND "B"."A1FK_NBR"="A"."A1FK_NBR" AND
"B"."A1FK_B_ID"="A"."A1FK_B_ID" AND "B"."A1FK_C_CD"="A"."A1FK_C_CD" AND
"B"."S1FK_C_ID"="A"."S1FK_C_ID" AND "B"."S1FK_CF_ID"="A"."S1FK_CF_ID" AND
"B"."S1FK_S_TYPE"="A"."S1FK_S_TYPE" AND "B"."S1FK_B_FUNC"="A"."S1FK_B_FUNC" AND
"B"."STACO1FK_A_TYPE"="A"."STACO1FK_A_TYPE")
filter("A"."IND"='Y' AND ("B"."IND"='N' OR
"B"."IND"="A"."IND") OR "B"."IND"=' ' AND
"A"."IND"=' ' AND "B"."AS1FK_A_ID"="A"."AS1FK_A_ID" AND
"B"."IND"="A"."IND")
EDIT
~~~~
I edited the above SQL to remove self-joins and unnecessary group-by.
I am doing grouping only on primary_secondary rows based on join.
Between primary and secondary, I am deciding the primary acct that should be plugged in for secondary.
This is giving the same result. I am wondering if this can be further improved.
WITH data
AS ( SELECT sanw.STAC01FK_C_ID,
sanw.STAC01FK_CF_ID,
sanw.STAC01FK_A_ID,
sanw.STACO1FK_A_TYPE,
sanw.STAC01FK_S_TYPE,
sanw.STAC01FK_B_FUNC,
BAU.ASAC01FK_A_ID,
BAU.ASAC01FK_B_FUNC,
BAU.ASAC01FK_S_TYPE,
BAU.ASAC01FK_TYPE_CODE,
BAAC02FK_BANK_ID,
BAAC02FK_NBR,
BAAC02FK_CURR_CD,
BAAC01FK_BANK_ID,
BAAC01FK_NBR,
BAAC01FK_CURR_CD,
BAU.R_NAME,
PRIMARY_ACCT_IND
FROM N_RULE cnr,
SAN sanw,
ACCT_USG bau
WHERE BAU.R_NAME = CNR.R_NAME
AND BAU.BAAC02FK_CURR_CD = CNR.C_CD
AND BAU.ASAC01FK_B_FUNC = CNR.B_FUNC_CD
AND BAU.ASAC01FK_A_ID = sanw.ASAC01FK_ID
AND BAU.ASAC01FK_B_FUNC = sanw.ASAC01FK_B_FUNC
AND BAU.ASAC01FK_S_TYPE = sanw.ASAC01FK_S_TYPE
AND BAU.ASAC01FK_TYPE_CODE = sanw.ASAC01FK_A_TYPE
AND CNR.FM_CODE = 'SP'
AND sanw.EFF_STATUS_CODE = 'A'
AND sanw.ASAC01FK_B_FUNC = CNR.B_FUNC_CD),
primary_secondary
AS (SELECT PRIMARY_ACCT_IND,
B.BAAC02FK_CURR_CD AS C_CD,
B.STAC01FK_C_ID AS C_ID_2,
B.STAC01FK_CF_ID AS CF_ID_2,
-- secondary accounts
B.STAC01FK_A_ID AS A_ID_2,
B.STAC01FK_B_FUNC AS B_FUNC_2,
B.STAC01FK_S_TYPE AS S_TYPE_2,
B.STACO1FK_A_TYPE AS A_TYPE_2,
--primary accounts
B.STAC01FK_A_ID AS A_ID_1,
B.STAC01FK_B_FUNC AS B_FUNC_1,
B.STAC01FK_S_TYPE AS S_TYPE_1,
B.STACO1FK_A_TYPE AS A_TYPE_1,
RANK ()
OVER (
PARTITION BY
--bank acct join
B.BAAC02FK_CURR_CD,
--sa join
B.STAC01FK_S_TYPE,
B.STAC01FK_B_FUNC,
B.STACO1FK_A_TYPE,
B.STAC01FK_C_ID,
B.STAC01FK_CF_ID
ORDER BY
PRIMARY_ACCT_IND DESC)
AS d_rank
FROM data B
WHERE B.PRIMARY_ACCT_IND IN ('Y', 'N')),
stand_alone
AS (SELECT B.BAAC02FK_CURR_CD AS C_CD,
B.STAC01FK_C_ID AS C_ID_2,
B.STAC01FK_CF_ID AS CF_ID_2,
-- secondary accounts
B.STAC01FK_A_ID AS A_ID_2,
B.STAC01FK_B_FUNC AS B_FUNC_2,
B.STAC01FK_S_TYPE AS S_TYPE_2,
B.STACO1FK_A_TYPE AS A_TYPE_2,
--primary accounts
B.STAC01FK_A_ID AS A_ID_1,
B.STAC01FK_B_FUNC AS B_FUNC_1,
B.STAC01FK_S_TYPE AS S_TYPE_1,
B.STACO1FK_A_TYPE AS A_TYPE_1
FROM data B
WHERE B.PRIMARY_ACCT_IND = ' '),
PRIMARY
AS (SELECT C_CD,
C_ID_2,
CF_ID_2,
-- secondary accounts
A_ID_2,
B_FUNC_2,
S_TYPE_2,
A_TYPE_2,
--primary accounts
A_ID_1,
B_FUNC_1,
S_TYPE_1,
A_TYPE_1
FROM primary_secondary
WHERE D_RANK = 1),
SECONDARY
AS (SELECT ps.C_CD,
ps.C_ID_2,
ps.CF_ID_2,
-- secondary accounts
ps.A_ID_2,
ps.B_FUNC_2,
ps.S_TYPE_2,
ps.A_TYPE_2,
--primary accounts
p.A_ID_1,
p.B_FUNC_1,
p.S_TYPE_1,
p.A_TYPE_1
FROM primary_secondary ps, primary p
WHERE ps.D_RANK <> 1
AND ps.C_CD = p.C_CD
AND ps.C_ID_2 = p.C_ID_2
AND ps.CF_ID_2 = p.CF_ID_2
-- secondarary accounts
AND ps.B_FUNC_2 = p.B_FUNC_2
AND ps.S_TYPE_2 = p.S_TYPE_2
AND ps.A_TYPE_2 = p.A_TYPE_2)
SELECT * FROM secondary
UNION ALL
SELECT * FROM primary
UNION ALL
SELECT * FROM stand_alone
PLAN:
Plan hash value: 3159296610
----------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 33 | 3421 | 9 (56)| 00:00:01 |
| 1 | TEMP TABLE TRANSFORMATION | | | | | |
| 2 | LOAD AS SELECT | SYS_TEMP_0FD9DBAF1_9261CF31 | | | | |
|* 3 | HASH JOIN | | 11 | 3058 | 119 (1)| 00:00:02 |
|* 4 | HASH JOIN | | 96 | 18816 | 104 (1)| 00:00:02 |
|* 5 | INDEX RANGE SCAN | CNR_PK | 61 | 1769 | 1 (0)| 00:00:01 |
| 6 | TABLE ACCESS FULL | ACCT_USG | 8244 | 1344K| 102 (0)| 00:00:02 |
|* 7 | TABLE ACCESS FULL | SAN | 1444 | 115K| 15 (0)| 00:00:01 |
| 8 | LOAD AS SELECT | SYS_TEMP_0FD9DBAF2_9261CF31 | | | | |
| 9 | WINDOW SORT | | 11 | 594 | 3 (34)| 00:00:01 |
|* 10 | VIEW | | 11 | 594 | 2 (0)| 00:00:01 |
| 11 | TABLE ACCESS FULL | SYS_TEMP_0FD9DBAF1_9261CF31 | 11 | 2343 | 2 (0)| 00:00:01 |
| 12 | LOAD AS SELECT | SYS_TEMP_0FD9DBAF3_9261CF31 | | | | |
|* 13 | VIEW | | 11 | 1089 | 2 (0)| 00:00:01 |
| 14 | TABLE ACCESS FULL | SYS_TEMP_0FD9DBAF2_9261CF31 | 11 | 682 | 2 (0)| 00:00:01 |
| 15 | UNION-ALL | | | | | |
|* 16 | HASH JOIN | | 11 | 1672 | 5 (20)| 00:00:01 |
|* 17 | VIEW | | 11 | 792 | 2 (0)| 00:00:01 |
| 18 | TABLE ACCESS FULL | SYS_TEMP_0FD9DBAF2_9261CF31 | 11 | 682 | 2 (0)| 00:00:01 |
| 19 | VIEW | | 11 | 880 | 2 (0)| 00:00:01 |
| 20 | TABLE ACCESS FULL | SYS_TEMP_0FD9DBAF3_9261CF31 | 11 | 946 | 2 (0)| 00:00:01 |
| 21 | VIEW | | 11 | 1067 | 2 (0)| 00:00:01 |
| 22 | TABLE ACCESS FULL | SYS_TEMP_0FD9DBAF3_9261CF31 | 11 | 946 | 2 (0)| 00:00:01 |
|* 23 | VIEW | | 11 | 682 | 2 (0)| 00:00:01 |
| 24 | TABLE ACCESS FULL | SYS_TEMP_0FD9DBAF1_9261CF31 | 11 | 2343 | 2 (0)| 00:00:01 |
----------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("BAU"."ASAC01FK_A_ID"="SANW"."ASAC01FK_ID"||'' AND
"BAU"."ASAC01FK_B_FUNC"="SANW"."ASAC01FK_B_FUNC" AND
"BAU"."ASAC01FK_S_TYPE"="SANW"."ASAC01FK_S_TYPE" AND
"BAU"."ASAC01FK_TYPE_CODE"="SANW"."ASAC01FK_A_TYPE" AND
"SANW"."ASAC01FK_B_FUNC"="CNR"."B_FUNC_CD")
4 - access("BAU"."R_NAME"="CNR"."R_NAME" AND
"BAU"."BAAC02FK_CURR_CD"="CNR"."C_CD" AND
"BAU"."ASAC01FK_B_FUNC"="CNR"."B_FUNC_CD")
5 - access("CNR"."FM_CODE"='SP')
7 - filter("SANW"."EFF_STATUS_CODE"='A')
10 - filter("B"."PRIMARY_ACCT_IND"='N' OR "B"."PRIMARY_ACCT_IND"='Y')
13 - filter("D_RANK"=1)
16 - access("PS"."C_CD"="P"."C_CD" AND "PS"."C_ID_2"="P"."C_ID_2" AND
"PS"."CF_ID_2"="P"."CF_ID_2" AND "PS"."B_FUNC_2"="P"."B_FUNC_2" AND
"PS"."S_TYPE_2"="P"."S_TYPE_2" AND "PS"."A_TYPE_2"="P"."A_TYPE_2")
17 - filter("PS"."D_RANK"<>1)
23 - filter("B"."PRIMARY_ACCT_IND"=' ')