Re: Query Transformation
- From: Patrick Jolliffe <jolliffe@xxxxxxxxx>
- To: oracle-l <oracle-l@xxxxxxxxxxxxx>
- Date: Thu, 28 Jan 2021 14:41:53 +0000
Thanks Jonathan,
(Hope I have ) Managed to reproduce it from scratch on a pristine 19.3
environment ('standard' Oracle docker image in this case).
Not hugely pleased about the SET_TABLE_STATS step, but we do what we can.
SQL for testcase and my output attached.
Going to keep on digging, just glad to have it confirmed that the plan is
indeed crazy and it's not (only) my ability to understand it lacking.
Best Regards
Patrick
On Thu, 28 Jan 2021 at 14:09, Jonathan Lewis <jlewisoracle@xxxxxxxxx> wrote:
I should have said that in my model both the varchar2() and nvarchar2()
plans produced exactly the same 4-branch concatenation.
The indications were then that the generation of the branch code is purely
formulaic and "unthinking" because in my case two of the branches had an
access predicate of
access("T1"."NV1"=U'0050')
followed in one case by the silly filter predicate of
filter(("T1"."NV1"<=U'0200' AND "T1"."NV1">=U'0100')
and in the other case by the even sillier filter predicate:
filter(("T1"."NV1"<=U'0200' AND "T1"."NV1">=U'0100') AND
LNNVL("T1"."NV1"=U'0050')))
Really the optimizer should have spotted the contradiction and filtered
out these two branches
This was all running 19.3.
Regards
Jonathan Lewis
On Wed, 27 Jan 2021 at 12:32, Patrick Jolliffe <jolliffe@xxxxxxxxx> wrote:
I *think* it's related to national characterset (NCHAR/NVARCHAR2). As
shown below (I hope) current testcase does not reproduce if I switch to
CHAR/VARCHAR2.
Investigation continues, trying to build complete reproducable testcase
from scratch.
SQL> drop table p purge;
Table P dropped.
SQL>
SQL> create table p nologging
2 as
3 with generator as (
4 select --+ materialize
5 rownum id
6 from dual
7 connect by
8 level <= 1e4
9 )
10 select ROWNUM rypyid,
11 cast (trim(to_char(MOD(ROWNUM, 10000), '099999999')) as
nvarchar2(10)) ryglba from
12 generator v1,
13 generator v2
14 where rownum <= 400000;
Table P created.
SQL>
SQL> alter table p add constraint p_pk primary key(rypyid);
Table P altered.
SQL> exec dbms_stats.gather_table_stats(null, 'p');
PL/SQL procedure successfully completed.
SQL>
SQL> drop table c1 purge;
Table C1 dropped.
SQL>
SQL> create table c1 nologging
2 as
3 with generator as (
4 select --+ materialize
5 rownum id
6 from dual
7 connect by
8 level <= 1e4
9 )
10 select
11 cast (trim(to_char(MOD(ROWNUM, 10000000), '099999999')) as
nvarchar2(10)) RZVR01,
12 MOD(ROWNUM, 1000000) RZPYID,
13 rpad('X', 255, 'X') padding
14 from
15 generator v1,
16 generator v2
17 where
18 rownum <= 16000000;
Table C1 created.
SQL>
SQL> CREATE INDEX c1_I ON c1 (RZVR01, RZPYID);
Index C1_I created.
SQL>
SQL> exec dbms_stats.gather_table_stats(null, 'c1');
PL/SQL procedure successfully completed.
SQL>
SQL> drop table c2 purge;
Table C2 dropped.
SQL>
SQL> create table c2 nologging
2 as
3 with generator as (
4 select --+ materialize
5 rownum id
6 from dual
7 connect by
8 level <= 1e4
9 )
10 select CAST(ROWNUM AS NCHAR(16)) gmaid,
11 cast (trim(to_char(MOD(ROWNUM, 1038), '099999999')) as nchar(12))
gmobj,
12 cast (trim(to_char(MOD(ROWNUM, 1441), '099999999')) as nchar(16))
gmsub,
13 rpad('X', 34, 'X') PADDING from
14 generator v1,
15 generator v2
16 where rownum <= 1000000;
Table C2 created.
SQL>
SQL> alter table c2 add constraint c2_pk primary key (gmaid);
Table C2 altered.
SQL> create index c2_i on c2(gmobj, gmsub, gmaid);
Index C2_I created.
SQL> exec dbms_stats.gather_table_stats(null, 'c2')
PL/SQL procedure successfully completed.
SQL>
SQL>
SQL> explain plan for SELECT /*+ OPT_PARAM('_optimizer_cbqt_or_expansion'
'off') P1 */ null FROM P, C1, C2 WHERE
2 ( ( C1.RZVR01 = :c1 AND C2.GMOBJ BETWEEN '2201' AND '2299') OR
3 ( C1.RZVR01 = :c2 AND C2.GMOBJ = '2019' AND C2.GMSUB = 'IDT' ) ) AND
4 ( P.rypyid = C1.RZPYID AND P.RYGLBA = C2.GMAID );
Explained.
SQL>
SQL> select * from dbms_xplan.display();
PLAN_TABLE_OUTPUT
____________________________________________________________________________________________
Plan hash value: 2640408289
-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
Time |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3 | 417 | 23 (0)|
00:00:01 |
| 1 | CONCATENATION | | | | |
|
| 2 | NESTED LOOPS | | 1 | 139 | 9 (0)|
00:00:01 |
| 3 | NESTED LOOPS | | 1 | 139 | 9 (0)|
00:00:01 |
| 4 | NESTED LOOPS | | 1 | 115 | 7 (0)|
00:00:01 |
|* 5 | INDEX RANGE SCAN | C2_I | 1 | 91 | 3 (0)|
00:00:01 |
| 6 | INLIST ITERATOR | | | | |
|
|* 7 | INDEX RANGE SCAN | C1_I | 1 | 24 | 4 (0)|
00:00:01 |
|* 8 | INDEX UNIQUE SCAN | P_PK | 1 | | 1 (0)|
00:00:01 |
|* 9 | TABLE ACCESS BY INDEX ROWID | P | 1 | 24 | 2 (0)|
00:00:01 |
| 10 | NESTED LOOPS | | 1 | 139 | 7 (0)|
00:00:01 |
| 11 | NESTED LOOPS | | 1 | 139 | 7 (0)|
00:00:01 |
| 12 | NESTED LOOPS | | 1 | 48 | 6 (0)|
00:00:01 |
|* 13 | INDEX RANGE SCAN | C1_I | 1 | 24 | 4 (0)|
00:00:01 |
| 14 | TABLE ACCESS BY INDEX ROWID| P | 1 | 24 | 2 (0)|
00:00:01 |
|* 15 | INDEX UNIQUE SCAN | P_PK | 1 | | 1 (0)|
00:00:01 |
|* 16 | INDEX UNIQUE SCAN | C2_PK | 1 | | 1 (0)|
00:00:01 |
|* 17 | TABLE ACCESS BY INDEX ROWID | C2 | 1 | 91 | 1 (0)|
00:00:01 |
| 18 | NESTED LOOPS | | 1 | 139 | 7 (0)|
00:00:01 |
| 19 | NESTED LOOPS | | 1 | 139 | 7 (0)|
00:00:01 |
| 20 | NESTED LOOPS | | 1 | 48 | 6 (0)|
00:00:01 |
|* 21 | INDEX RANGE SCAN | C1_I | 1 | 24 | 4 (0)|
00:00:01 |
| 22 | TABLE ACCESS BY INDEX ROWID| P | 1 | 24 | 2 (0)|
00:00:01 |
|* 23 | INDEX UNIQUE SCAN | P_PK | 1 | | 1 (0)|
00:00:01 |
|* 24 | INDEX UNIQUE SCAN | C2_PK | 1 | | 1 (0)|
00:00:01 |
|* 25 | TABLE ACCESS BY INDEX ROWID | C2 | 1 | 91 | 1 (0)|
00:00:01 |
-----------------------------------------------------------------------------------------
PLAN_TABLE_OUTPUT
_________________________________________________________________________________________________
Predicate Information (identified by operation id):
---------------------------------------------------
5 - access("C2"."GMOBJ"=U'2019' AND "C2"."GMSUB"=U'IDT')
7 - access("C1"."RZVR01"=SYS_OP_C2C(:C1) OR "C1"."RZVR01"=SYS_OP_C2C(:C2))
filter("C1"."RZVR01"=SYS_OP_C2C(:C1) AND "C2"."GMOBJ">=U'2201' AND
"C2"."GMOBJ"<=U'2299' OR "C1"."RZVR01"=SYS_OP_C2C(:C2) AND
"C2"."GMOBJ"=U'2019'
AND "C2"."GMSUB"=U'IDT')
8 - access("P"."RYPYID"="C1"."RZPYID")
9 - filter("P"."RYGLBA"="C2"."GMAID")
13 - access("C1"."RZVR01"=SYS_OP_C2C(:C2))
filter("C1"."RZVR01"=SYS_OP_C2C(:C1) OR "C1"."RZVR01"=SYS_OP_C2C(:C2))
15 - access("P"."RYPYID"="C1"."RZPYID")
16 - access("P"."RYGLBA"="C2"."GMAID")
17 - filter("C2"."GMSUB"=U'IDT' AND "C2"."GMOBJ"=U'2019' AND
"C2"."GMOBJ">=U'2201' AND "C2"."GMOBJ"<=U'2299' AND
(LNNVL("C2"."GMSUB"=U'IDT')
OR LNNVL("C2"."GMOBJ"=U'2019')))
21 - access("C1"."RZVR01"=SYS_OP_C2C(:C1))
filter("C1"."RZVR01"=SYS_OP_C2C(:C1) OR "C1"."RZVR01"=SYS_OP_C2C(:C2))
23 - access("P"."RYPYID"="C1"."RZPYID")
24 - access("P"."RYGLBA"="C2"."GMAID")
25 - filter("C2"."GMOBJ">=U'2201' AND "C2"."GMOBJ">=U'2201' AND
"C2"."GMOBJ"<=U'2299' AND "C2"."GMOBJ"<=U'2299' AND
(LNNVL("C1"."RZVR01"=SYS_OP_C2C(:C2)) OR
LNNVL("C2"."GMOBJ"=U'2019') OR
LNNVL("C2"."GMSUB"=U'IDT')) AND (LNNVL("C2"."GMSUB"=U'IDT') OR
LNNVL("C2"."GMOBJ"=U'2019')))
Hint Report (identified by operation id / Query Block Name / Object Alias):
Total hints for statement: 1 (E - Syntax error (1))
---------------------------------------------------------------------------
1 - SEL$1
E - P1
66 rows selected.
Attachment:
crazy_plan.sql
Description: Binary data
Other related posts: