Hi
it's almost one week that i struggle with a simple query.
The main problem is that query runned on a specific db instance of a server (the db istance that i usually use every day)
produce a merge join cartesian in Explain Plan output, while if i run that query from another db istance \ sever the execution plan show me a different access and in this case the query after 10 minute throw me a output.
This is the query:
--from Oracle 11.2.0.4.0
WITH first_event_year AS (
SELECT DISTINCT key_paz,
first_value(RI) over(PARTITION BY key_paz ORDER BY t_erog) AS fri
FROM (
SELECT key_ass, t_erog, ROWID AS ri
FROM SC0029 /*synonim for a table out of the db istance the query is running (Oracle 12.1.0.2.0)*/
WHERE anno = '2017'
AND ( c_prest = '87.37.1' OR c_catamb = 'C00270100' )
AND C_REGAPP = '070'
AND TIP_PRES = 'S'
) s,
CORRELAZIONE K /*synonim for a table out of the db istance the query is running (same db istance of SC0029)*/
WHERE S.key_ass = K.key_ass
)
--main query
SELECT asl_dedotta,
COUNT(*)
FROM (
SELECT s2.c_comres /*I get in this case only a field, but i could retrieve more fieds*/
FROM SC0029 s2, /*synonim for a table out of the db istance the query is running*/
first_event_year P
WHERE s2.ROWID = p.fri
) Y,
(
SELECT codice, asl_dedotta
FROM comuni -- local table
WHERE codreg = '070'
) C
WHERE Y.c_comres = C.codice
GROUP BY C.asl_dedotta
ORDER BY C.asl_dedotta
Considering only the temporary table (first_event_year), if I run the explain plan tool I can see nothing strange and the output is generated in about 10 minutes.
I'm talking about 60,000 records from a table (SC0029) populated by about 200 milion of records (20M X year from 2010)
But if i run the explain plan tool of the whole statements i see that
Plan
10 SELECT STATEMENT ALL_ROWS
Cost: 587.360; Bytes: 21.310; Cardinality: 5; CPU Cost: 0; IO Cost: 0; Time: 00:00:00;
Partition #: 0;
9 SORT ORDER BY
Projection: (#keys=1) NLSSORT("ASL_DEDOTTA",'nls_sort=''WEST_EUROPEAN''')[34], "ASL_DEDOTTA"[VARCHAR2,3], COUNT(*)[22];
Cost: 587.360; Bytes: 21.310; Cardinality: 5; CPU Cost: 0; IO Cost: 0; Time: 00:00:00;
Partition #: 0;
8 HASH GROUP BY
Projection: (#keys=1) "ASL_DEDOTTA"[VARCHAR2,3], COUNT(*)[22];
Cost: 587.360; Bytes: 21.310; Cardinality: 5; CPU Cost: 0; IO Cost: 0; Time: 00:00:00;
Partition #: 0;
7 NESTED LOOPS
Projection: (#keys=0) "ASL_DEDOTTA"[VARCHAR2,3];
Cost: 672.152; Bytes: 1.467.641.548; Cardinality: 11.429.442; CPU Cost: 0; IO Cost: 0; Time: 00:00:00;
Partition #: 0;
5 <b>MERGE JOIN CARTESIAN</b>
Projection: (#keys=0) "P"."FRI"[ROWID,4000], "CODICE"[VARCHAR2,6], "ASL_DEDOTTA"[VARCHAR2,3];
Cost: 634; Bytes: 35.058.980; Cardinality: 8.732; CPU Cost: 0; IO Cost: 0; Time: 00:00:00;
Partition #: 0;
2 VIEW ARS.
Projection: "P"."FRI"[ROWID,4000];
Cost: 86; Bytes: 148.074; Cardinality: 37; CPU Cost: 0; IO Cost: 0; Time: 00:00:00;
Partition #: 0;
1 REMOTE SERIAL_FROM_REMOTE DBFNEW.REGLIG
EXPLAIN PLAN SET STATEMENT_ID='E0D58D52' INTO "ARS"."SQLN_EXPLAIN_PLAN"@! FOR SELECT DISTINCT "A1"."KEY_PAZ",FIRST_VALUE("A2".ROWID) OVER ( PARTITION BY "A1"."KEY_PAZ" ORDER BY "A2"."T_EROG" RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) FROM "SISG"."SC0029" "A2","SISG"."CORRELAZIONE" "A1" WHERE "A2"."KEY_ASS"="A1"."KEY_ASS" AND "A2"."ANNO"='2017' AND ("A2"."C_PREST"='87.37.1' OR "A2"."C_CATAMB"='C00270100') AND "A2"."C_REGAPP"='070' AND "A2"."TIP_PRES"='S'
Projection: "KEY_PAZ"[NUMBER,22], FIRST_VALUE(ROWID) OVER ( PARTITION BY "KEY_PAZ" ORDER BY "T_EROG" RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW )[4000];
Cost: 0; Bytes: 0; Cardinality: 0; CPU Cost: 0; IO Cost: 0;
Partition #: 0;
4 BUFFER SORT
Projection: (#keys=0) "CODICE"[VARCHAR2,6], "ASL_DEDOTTA"[VARCHAR2,3];
Cost: 634; Bytes: 3.068; Cardinality: 236; CPU Cost: 0; IO Cost: 0; Time: 00:00:00;
Partition #: 0;
3 TABLE ACCESS FULL ARS.COMUNI
Filter: "CODREG"='070';
Projection: "CODICE"[VARCHAR2,6], "ASL_DEDOTTA"[VARCHAR2,3];
Cost: 15; Bytes: 3.068; Cardinality: 236; CPU Cost: 0; IO Cost: 0; Time: 00:00:00;
Partition #: 0;
6 REMOTE SERIAL_FROM_REMOTE SC0029 DBFNEW.REGLIG
SELECT ROWID,"C_COMRES" FROM "SISG"."SC0029" "S2" WHERE "C_COMRES"=:1 AND ROWID=:2
Projection: "S2".ROWID[ROWID,4000], "S2"."C_COMRES"[VARCHAR2,6];
Cost: 67; Bytes: 323.323; Cardinality: 1.309; CPU Cost: 0; IO Cost: 0; Time: 00:00:00;
Partition #: 0;
With that "merge join cartesian" the query does not throw out any result in the useful time of a weekend!
Then I'have also tried to reverse the query from the other server view.
To do that I had to grant the select privilege to COMUNI table.
This is the "reversed" query:
WITH first_event_year AS (
SELECT DISTINCT key_paz,
first_value(RI) over(PARTITION BY key_paz ORDER BY t_erog) AS fri
FROM (
SELECT key_ass, t_erog, ROWID AS ri
FROM SC0029 --LOCAL TABLE NOW
WHERE anno = '2017'
AND ( c_prest = '87.37.1' OR c_catamb = 'C00270100' )
AND C_REGAPP = '070'
AND TIP_PRES = 'S'
) s,
CORRELAZIONE K --LOCAL TABLE NOW
WHERE S.key_ass = K.key_ass
)
SELECT asl_dedotta,
COUNT(*)
FROM (
SELECT s2.c_comres
FROM SC0029 s2,
first_event_year P
WHERE s2.ROWID = p.fri
) Y,
(
SELECT codice, asl_dedotta
FROM ARS.comuni@MY_DBLINK /*table throught dblink*/
WHERE codreg = '070'
) C
WHERE Y.c_comres = C.codice
GROUP BY C.asl_dedotta
ORDER BY C.asl_dedotta.
Written in that way the query don't generate any merge join cartesian and ends in about 10 minutes.
But the VERY STRANGE thing (for me) that I discover after one week, is that if I take back the first query and I change the query row...
from:
first_value(RI) over(PARTITION BY key_paz ORDER BY t_erog) AS fri
to:
first_value(S.ROWID) over(PARTITION BY key_paz ORDER BY t_erog) AS fri
the same query doesn't generate any merge join cartesian end in about 10 minutes with this execution plan:
Plan
9 SELECT STATEMENT ALL_ROWS
Cost: 16.204; Bytes: 1.360; Cardinality: 5; CPU Cost: 0; IO Cost: 0; Time: 00:00:00;
Partition #: 0;
8 SORT ORDER BY
Projection: (#keys=1) NLSSORT("ASL_DEDOTTA",'nls_sort=''WEST_EUROPEAN''')[34], "ASL_DEDOTTA"[VARCHAR2,3], COUNT(*)[22];
Cost: 16.204; Bytes: 1.360; Cardinality: 5; CPU Cost: 0; IO Cost: 0; Time: 00:00:00;
Partition #: 0;
7 HASH GROUP BY
Projection: (#keys=1) "ASL_DEDOTTA"[VARCHAR2,3], COUNT(*)[22];
Cost: 16.204; Bytes: 1.360; Cardinality: 5; CPU Cost: 0; IO Cost: 0; Time: 00:00:00;
Partition #: 0;
6 HASH JOIN
Access: "P"."FRI"=("S2".ROWID);
Projection: (#keys=1) "ASL_DEDOTTA"[VARCHAR2,3];
Cost: 15.957; Bytes: 621.761.536; Cardinality: 2.285.888; CPU Cost: 0; IO Cost: 0; Time: 00:00:00;
Partition #: 0;
2 VIEW ARS.
Projection: "P"."FRI"[ROWID,10];
Cost: 86; Bytes: 444; Cardinality: 37; CPU Cost: 0; IO Cost: 0; Time: 00:00:00;
Partition #: 0;
1 REMOTE SERIAL_FROM_REMOTE DBFNEW.REGLIG
EXPLAIN PLAN SET STATEMENT_ID='E0D593CE' INTO "ARS"."SQLN_EXPLAIN_PLAN"@! FOR SELECT DISTINCT "A1"."KEY_PAZ",FIRST_VALUE("A2".ROWID) OVER ( PARTITION BY "A1"."KEY_PAZ" ORDER BY "A2"."T_EROG" RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) FROM "SISG"."SC0029" "A2","SISG"."CORRELAZIONE" "A1" WHERE "A2"."KEY_ASS"="A1"."KEY_ASS" AND "A2"."ANNO"='2017' AND ("A2"."C_PREST"='87.37.1' OR "A2"."C_CATAMB"='C00270100') AND "A2"."C_REGAPP"='070' AND "A2"."TIP_PRES"='S'
Projection: "KEY_PAZ"[NUMBER,22], FIRST_VALUE("S".ROWID) OVER ( PARTITION BY "KEY_PAZ" ORDER BY "T_EROG" RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW )[10];
Cost: 0; Bytes: 0; Cardinality: 0; CPU Cost: 0; IO Cost: 0;
Partition #: 0;
5 NESTED LOOPS
Projection: (#keys=0) "ASL_DEDOTTA"[VARCHAR2,3], "S2".ROWID[ROWID,4000];
Cost: 62.406; Bytes: 1.606.300.020; Cardinality: 6.178.077; CPU Cost: 0; IO Cost: 0; Time: 00:00:00;
Partition #: 0;
3 TABLE ACCESS FULL ARS.COMUNI
Filter: "CODREG"='070';
Projection: "CODICE"[VARCHAR2,6], "ASL_DEDOTTA"[VARCHAR2,3];
Cost: 16; Bytes: 3.068; Cardinality: 236; CPU Cost: 0; IO Cost: 0; Time: 00:00:00;
Partition #: 0;
4 REMOTE SERIAL_FROM_REMOTE SC0029 DBFNEW.REGLIG
SELECT ROWID,"C_COMRES" FROM "SISG"."SC0029" "S2" WHERE "C_COMRES"=:1
Projection: "S2".ROWID[ROWID,4000], "S2"."C_COMRES"[VARCHAR2,6];
Cost: 67; Bytes: 6.465.966; Cardinality: 26.178; CPU Cost: 0; IO Cost: 0; Time: 00:00:00;
Partition #: 0;
How can it be that an column alias change so heavy the execution plan?
Than you in advance
In the first query, the database joins first_event_year to comuni.
But there's no join between these! So it has to use a merge join.
Whereas in the second query, it joins comuni to SC0029. Which does have a join predicate. Then links to the first_event_year subquery.
Exactly why this happens I'm not sure!
Going over a database link has many limitations. Without the alias, I suspect the database is no longer able to infer that FRI returns the ROWID from the subquery. Leading to the merge join.
In any case, I see you access SC0029 twice.
Is this really necessary?
If you can change the query so you only access it once, not only is your query likely to be quicker due to reducing the number of table accesses, there's less chance for the optimizer to get the plan wrong!