Hi Chris
Thank you for your answer. I have looked deep into it.
The SQL in the original question is actually not our real problem, but a narrow down to demonstrate the issue.
Our real issue is the 2 views below:
CREATE OR REPLACE FORCE EDITIONABLE VIEW "EAN"."table_1_BASIS" ("ME_ID", "GEOMETRI", fk_sagspakke_id) AS
SELECT /*+ QB_NAME(mat_basis) */
ms.id me_id,
ms.geometri,
ms.fk_sagspakke_id
FROM user_1.table_1 ms
WHERE ms.enum_variant IN (1, 2);
CREATE OR REPLACE FORCE EDITIONABLE VIEW "EAN"."table_1_SAG" ("ME_ID", "GEOMETRI", "JOURNALNR", "SAGSID") AS
SELECT /*+ NO_INDEX(@mat_basis ms table_1_GEOMETRI_RT) */
ms.me_id,
ms.geometri,
s.journal journalnr,
s.sagsid sagsid
FROM user_1.sag s
JOIN ean.table_1_basis ms ON ms.fk_sagspakke_id = s.fk_sagspakke_id;
In the 2 views I have implemented promoting of index prevention from outer view to inner view. It works fine.
After view creation running this SQL:
SELECT *
FROM ean.table_1_SAG A
WHERE
SAGSID = 100042140
AND (MDSYS.SDO_RELATE(A.GEOMETRI, MDSYS.SDO_GEOMETRY(2003, 25832, NULL, MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,1), MDSYS.SDO_ORDINATE_ARRAY(
294245.130000, 6454399.952465,
294245.130000, 5997123.197535,
1040726.720000, 5997123.197535,
1040726.720000, 6454399.952465,
294245.130000, 6454399.952465)), 'mask=ANYINTERACT querytype=window') = 'TRUE');
using SQLPlus commands:
set autotrace off
SET SERVEROUTPUT off
set line 200
set echo off
set term off
spool trace.log
alter session set statistics_level = all;
timing start
SELECT *
FROM ean.table_1_SAG A
WHERE
SAGSID = 100042140
AND (MDSYS.SDO_RELATE(A.GEOMETRI, MDSYS.SDO_GEOMETRY(2003, 25832, NULL, MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,1), MDSYS.SDO_ORDINATE_ARRAY(
294245.130000, 6454399.952465,
294245.130000, 5997123.197535,
1040726.720000, 5997123.197535,
1040726.720000, 6454399.952465,
294245.130000, 6454399.952465)), 'mask=ANYINTERACT querytype=window') = 'TRUE');
set term on
select * from table(dbms_xplan.display_cursor);
timing stop
spool off
I get this execution plan:
SQL> @exe_plan.sql
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------
SQL_ID dknbnjdfkgrqm, child number 4
-------------------------------------
SELECT * FROM ean.table_1_SAG A WHERE SAGSID = 100042140 AND
(MDSYS.SDO_RELATE(A.GEOMETRI, MDSYS.SDO_GEOMETRY(2003, 25832, NULL,
MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,1), MDSYS.SDO_ORDINATE_ARRAY(
294245.130000, 6454399.952465, 294245.130000, 5997123.197535,
1040726.720000, 5997123.197535, 1040726.720000, 6454399.952465,
294245.130000, 6454399.952465)), 'mask=ANYINTERACT querytype=window')
= 'TRUE')
Plan hash value: 1249522991
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 3520 (100)| |
| 1 | NESTED LOOPS | | 248 | 46128 | 3520 (98)| 00:00:01 |
|* 2 | TABLE ACCESS BY INDEX ROWID | SAG | 1 | 22 | 3 (0)| 00:00:01 |
|* 3 | INDEX UNIQUE SCAN | SYS_C006847 | 1 | | 2 (0)| 00:00:01 |
|* 4 | TABLE ACCESS BY INDEX ROWID BATCHED| table_1 | 248 | 40672 | 3517 (98)| 00:00:01 |
|* 5 | INDEX RANGE SCAN | table_1_FK_SAGSPAKKE_IDX | 1682 | | 3 (0)| 00:00:01 |
----------------------------------------------------------------------------------------------------------------------
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("S"."FK_SAGSPAKKE_ID" IS NOT NULL)
3 - access("S"."SAGSID"=100042140)
4 - filter((INTERNAL_FUNCTION("MS"."ENUM_VARIANT") AND
"MDSYS"."SDO_RELATE"("MS"."GEOMETRI","MDSYS"."SDO_GEOMETRY"(2003,25832,NULL,"MDSYS"."SDO_ELEM_INFO_ARRAY"(1,10
03,1),"MDSYS"."SDO_ORDINATE_ARRAY"(294245.13,6454399.952465,294245.13,5997123.197535,1040726.72,5997123.197535
,1040726.72,6454399.952465,294245.13,6454399.952465)),'mask=ANYINTERACT querytype=window')='TRUE'))
5 - access("MS"."FK_SAGSPAKKE_ID"="S"."FK_SAGSPAKKE_ID")
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------
filter("MS"."FK_SAGSPAKKE_ID" IS NOT NULL)
Note
-----
- statistics feedback used for this statement
39 rows selected.
Elapsed: 00:00:02.65
Until now everything is ok.
The 2 views actually need more joins to fulfill business requirements. I therefore add yet another join and recreate views:
CREATE OR REPLACE FORCE EDITIONABLE VIEW "EAN"."table_1_BASIS" ("ME_ID", "GEOMETRI", fk_sagspakke_id) AS
SELECT /*+ QB_NAME(mat_basis) USE_NL(ms sp1) */
ms.id me_id,
ms.geometri,
ms.fk_sagspakke_id
FROM user_1.table_1 ms
inner JOIN user_1.table_2 sp1 on sp1.id = ms.fk_frapunkt_id
WHERE ms.enum_variant IN (1, 2);
CREATE OR REPLACE FORCE EDITIONABLE VIEW "EAN"."table_1_SAG" ("ME_ID", "GEOMETRI", "JOURNALNR", "SAGSID") AS
SELECT /*+ NO_INDEX(@mat_basis ms table_1_GEOMETRI_RT) */
ms.me_id,
ms.geometri,
s.journal journalnr,
s.sagsid sagsid
FROM user_1.sag s
JOIN ean.table_1_basis ms ON ms.fk_sagspakke_id = s.fk_sagspakke_id;
I now execute test SQL again:
SELECT *
FROM ean.table_1_SAG A
WHERE
SAGSID = 100042140
AND (MDSYS.SDO_RELATE(A.GEOMETRI, MDSYS.SDO_GEOMETRY(2003, 25832, NULL, MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,1), MDSYS.SDO_ORDINATE_ARRAY(
294245.130000, 6454399.952465,
294245.130000, 5997123.197535,
1040726.720000, 5997123.197535,
1040726.720000, 6454399.952465,
294245.130000, 6454399.952465)), 'mask=ANYINTERACT querytype=window') = 'TRUE');
Test SQL now runs for 4,5 minute.
Then I execute select * from table(dbms_xplan.display_cursor) saying:
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------
--------------------------------------------------
SQL_ID dknbnjdfkgrqm, child number 5
-------------------------------------
SELECT * FROM ean.table_1_SAG A WHERE SAGSID = 100042140 AND
(MDSYS.SDO_RELATE(A.GEOMETRI, MDSYS.SDO_GEOMETRY(2003, 25832, NULL,
MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,1), MDSYS.SDO_ORDINATE_ARRAY(
294245.130000, 6454399.952465, 294245.130000, 5997123.197535,
1040726.720000, 5997123.197535, 1040726.720000, 6454399.952465,
294245.130000, 6454399.952465)), 'mask=ANYINTERACT querytype=window')
= 'TRUE')
Plan hash value: 2222986838
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 21 (100)| |
| 1 | NESTED LOOPS | | 248 | 46128 | 21 (0)| 00:00:01 |
|* 2 | TABLE ACCESS BY INDEX ROWID | SAG | 1 | 22 | 3 (0)| 00:00:01 |
|* 3 | INDEX UNIQUE SCAN | SYS_C006847 | 1 | | 2 (0)| 00:00:01 |
|* 4 | TABLE ACCESS BY INDEX ROWID BATCHED| table_1 | 248 | 40672 | 21 (0)| 00:00:01 |
| 5 | BITMAP CONVERSION TO ROWIDS | | | | | |
| 6 | BITMAP AND | | | | | |
| 7 | BITMAP CONVERSION FROM ROWIDS | | | | | |
|* 8 | INDEX RANGE SCAN | table_1_FK_SAGSPAKKE_IDX | 1682 | | 3 (0)| 00:00:01 |
| 9 | BITMAP CONVERSION FROM ROWIDS | | | | | |
| 10 | SORT ORDER BY | | | | | |
| 11 | DOMAIN INDEX (SEL: 0.100000 %)| table_1_GEOMETRI_RT | 1682 | | 6 (0)| 00:00:01 |
----------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("S"."FK_SAGSPAKKE_ID" IS NOT NULL)
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------------------------------
3 - access("S"."SAGSID"=100042140)
4 - filter((INTERNAL_FUNCTION("MS"."ENUM_VARIANT") AND "MS"."FK_FRAPUNKT_ID" IS NOT NULL))
8 - access("MS"."FK_SAGSPAKKE_ID"="S"."FK_SAGSPAKKE_ID")
filter("MS"."FK_SAGSPAKKE_ID" IS NOT NULL)
Note
-----
- statistics feedback used for this statement
At this step I think it is strange to use 4,5 minute to handle less than 2000 rows in above execution plan.
I therefore trace test SQL and get
Statistics
----------------------------------------------------------
3277528 recursive calls
21 db block gets
2187268 consistent gets
550994 physical reads
0 redo size
43509 bytes sent via SQL*Net to client
1046 bytes received via SQL*Net from client
25 SQL*Net roundtrips to/from client
1 sorts (memory)
1 sorts (disk)
248 rows processed
Elapsed: 00:04:34.27
And this explains it for me: SQL is executed in 4,5 minute due to 2.2 mio buffer gets (0.5 mio being even physical gets)
My question is now: how come these 2.2 mio buffer gets do not show up in execution plan extracted by select * from table(dbms_xplan.display_cursor) above?
Anyway, I try execute dbms_xplan.display_cursor based on SQLId as suggested in your guide:
select * from table(dbms_xplan.display_cursor('dknbnjdfkgrqm', null, 'ALLSTATS LAST'));
and I get
SQL_ID dknbnjdfkgrqm, child number 5
-------------------------------------
SELECT * FROM ean.table_1_SAG A WHERE SAGSID = 100042140 AND
(MDSYS.SDO_RELATE(A.GEOMETRI, MDSYS.SDO_GEOMETRY(2003, 25832, NULL,
MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,1), MDSYS.SDO_ORDINATE_ARRAY(
294245.130000, 6454399.952465, 294245.130000, 5997123.197535,
1040726.720000, 5997123.197535, 1040726.720000, 6454399.952465,
294245.130000, 6454399.952465)), 'mask=ANYINTERACT querytype=window')
= 'TRUE')
Plan hash value: 2222986838
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | Writes | OMem | 1Mem | Used-Mem | Used-Tmp|
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 248 |00:04:31.35 | 2187K| 550K| 193K| | | | |
| 1 | NESTED LOOPS | | 1 | 248 | 248 |00:04:31.35 | 2187K| 550K| 193K| | | | |
|* 2 | TABLE ACCESS BY INDEX ROWID | SAG | 1 | 1 | 1 |00:00:00.01 | 4 | 0 | 0 | | | | |
|* 3 | INDEX UNIQUE SCAN | SYS_C006847 | 1 | 1 | 1 |00:00:00.01 | 3 | 0 | 0 | | | | |
|* 4 | TABLE ACCESS BY INDEX ROWID BATCHED| table_1 | 1 | 248 | 248 |00:04:31.35 | 2187K| 550K| 193K| | | | |
| 5 | BITMAP CONVERSION TO ROWIDS | | 1 | | 248 |00:04:31.35 | 2187K| 550K| 193K| | | | |
| 6 | BITMAP AND | | 1 | | 1 |00:04:31.35 | 2187K| 550K| 193K| | | | |
| 7 | BITMAP CONVERSION FROM ROWIDS | | 1 | | 1 |00:00:00.01 | 4 | 0 | 0 | | | | |
|* 8 | INDEX RANGE SCAN | table_1_FK_SAGSPAKKE_IDX | 1 | 1682 | 248 |00:00:00.01 | 4 | 0 | 0 | | | | |
| 9 | BITMAP CONVERSION FROM ROWIDS | | 1 | | 1 |00:04:31.35 | 2187K| 550K| 193K| | | | |
| 10 | SORT ORDER BY | | 1 | | 8029K|00:04:30.42 | 2187K| 550K| 193K| 848M| 9525K| 100M (1)| 761K|
| 11 | DOMAIN INDEX (SEL: 0.100000 %)| table_1_GEOMETRI_RT | 1 | 1682 | 49M|00:03:41.37 | 2187K| 438K| 0 | | | | |
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("S"."FK_SAGSPAKKE_ID" IS NOT NULL)
3 - access("S"."SAGSID"=100042140)
4 - filter((INTERNAL_FUNCTION("MS"."ENUM_VARIANT") AND "MS"."FK_FRAPUNKT_ID" IS NOT NULL))
8 - access("MS"."FK_SAGSPAKKE_ID"="S"."FK_SAGSPAKKE_ID")
filter("MS"."FK_SAGSPAKKE_ID" IS NOT NULL)
Note
-----
- statistics feedback used for this statement
This output says that 49mio rows are visited in line 11 in geo index compared to expected visit of 1682 rows.
Even though we advice SQL not to use index table_1_GEOMETRI_RT, it now use it.
How do we prevent SQL using geo index in bitmap conversions?
Best Regards
Erik