Data inconsistency cases caused by predicate pushing

Keywords: Oracle SQL

phenomenon

The following statement can find the record of deviceid DEV005M0, but with the condition of deviceid ='DEV005M0', the query statement can not find the result.
Statements are as follows:

select * from 
(    select deviceid deviceid, port, cvlan, status, funcswitch, 
            decode(funcswitch, 3, pvlan, 1, pvlan) svlan,
            decode(funcswitch, 3, pvlan, 1, 
            lead(pvlan)over(partition by deviceid, port, cvlan, status order by pvlan asc)) evlan
     from   vlanstatus_pre2bak
)
where  funcswitch <> 2 and evlan is null  -- and  deviceid = 'DEV005M0';

When the deviceid ='DEV005M0'is commented out, the query results are as follows:

When deviceid = DEV005M0 is added, the query result is not recorded:

The data type of deviceid is char (8). The deviceid data of vlanstatus_pre2bak has no special characters such as spaces, which is very weird. Next comes the concrete analysis.

The analysis is as follows

1. Query statement, query not recorded

select * from 
(    select deviceid deviceid, port, cvlan, status, funcswitch, 
            decode(funcswitch, 3, pvlan, 1, pvlan) svlan,
            decode(funcswitch, 3, pvlan, 1, 
            lead(pvlan)over(partition by deviceid, port, cvlan, status order by pvlan asc)) evlan
     from   vlanstatus_pre2bak
)
where  funcswitch <> 2 and evlan is null  and  deviceid = 'DEV005M0' ;

Or:

with tmptab as
(    
    select  deviceid deviceid, port, cvlan, status, funcswitch, 
            decode(funcswitch, 3, pvlan, 1, pvlan) svlan,
            decode(funcswitch, 3, pvlan, 1, 
            lead(pvlan)over(partition by deviceid, port, cvlan, status order by pvlan asc)) evlan
     from   vlanstatus_pre2bak
)
select * from tmptab 
where  funcswitch <> 2 and evlan is null  and  deviceid = 'DEV005M0' ;

View the implementation plan:

SQL> set lines 200
SQL> set pages 200
SQL> explain plan for
  2  select * from 
  3  (    select deviceid deviceid, port, cvlan, status, funcswitch, 
  4              decode(funcswitch, 3, pvlan, 1, pvlan) svlan,
  5              decode(funcswitch, 3, pvlan, 1, 
  6              lead(pvlan)over(partition by deviceid, port, cvlan, status order by pvlan asc)) evlan
  7       from   vlanstatus_pre2bak
  8  )
  9  where  funcswitch <> 2 and evlan is null  and  deviceid = 'DEV005M0' ;

//It has been explained.

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
Plan hash value: 2175325539

------------------------------------------------------------------------------------------
| Id  | Operation           | Name               | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |                    |    70 | 49350 |   692   (1)| 00:00:09 |
|*  1 |  VIEW               |                    |    70 | 49350 |   692   (1)| 00:00:09 |
|   2 |   WINDOW SORT       |                    |    70 |  3430 |   692   (1)| 00:00:09 |
|*  3 |    TABLE ACCESS FULL| VLANSTATUS_PRE2BAK |    70 |  3430 |   691   (1)| 00:00:09 |
------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("FUNCSWITCH"<>2 AND "EVLAN" IS NULL)
   3 - filter("DEVICEID"='DEV005M0')

//Sixteen rows have been selected.

SQL> 

Look at the predicate filter with ID 3 (3 - filter("DEVICEID"='DEV005M0'), indicating that the deviceid ='DEV005M0'operation was performed first in table VLANSTATUS_PRE2BAK. There are only two predicate filters with ID 1 (1 - filter ("FUNCSWITCH"<> 2 AND "EVLAN" IS NULL). This indicates that the query first filters the record of deviceid ='DEV005M0'in the sub-query, and then performs the filtering condition FUNCSWITCH<> 2 AND EVLAN IS NULL in the whole query view. This phenomenon is predicate pushing.

2. Use materialize hint to avoid predicate pushing

with tmptab as
(    
    select  /*+materialize*/ deviceid deviceid, port, cvlan, status, funcswitch, 
            decode(funcswitch, 3, pvlan, 1, pvlan) svlan,
            decode(funcswitch, 3, pvlan, 1, 
            lead(pvlan)over(partition by deviceid, port, cvlan, status order by pvlan asc)) evlan
     from   vlanstatus_pre2bak
)
select * from tmptab 
where  funcswitch <> 2 and evlan is null  and  deviceid = 'DEV005M0' ;

SQL> set lines 200
SQL> set pages 200
SQL> explain plan for 
  2  with tmptab as
  3  (    
  4      select  /*+materialize*/ deviceid deviceid, port, cvlan, status, funcswitch, 
  5              decode(funcswitch, 3, pvlan, 1, pvlan) svlan,
  6              decode(funcswitch, 3, pvlan, 1, 
  7              lead(pvlan)over(partition by deviceid, port, cvlan, status order by pvlan asc)) evlan
  8       from   vlanstatus_pre2bak
  9  )
 10  select * from tmptab 
 11  where  funcswitch <> 2 and evlan is null  and  deviceid = 'DEV005M0' ;

//It has been explained.

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
Plan hash value: 1444871666

----------------------------------------------------------------------------------------------------
| Id  | Operation                  | Name                        | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT           |                             |   313K|   210M|       |  5062   (1)| 00:01:01 |
|   1 |  TEMP TABLE TRANSFORMATION |                             |       |       |       |            |          |
|   2 |   LOAD AS SELECT           | SYS_TEMP_0FD9D66CE_DF9DBBFB |       |       |       |            |          |
|   3 |    WINDOW SORT             |                             |   313K|    14M|    20M|  4492   (1)| 00:00:54 |
|   4 |     TABLE ACCESS FULL      | VLANSTATUS_PRE2BAK          |   313K|    14M|       |   690   (1)| 00:00:09 |
|*  5 |   VIEW                     |                             |   313K|   210M|       |   570   (1)| 00:00:07 |
|   6 |    TABLE ACCESS FULL       | SYS_TEMP_0FD9D66CE_DF9DBBFB |   313K|    14M|       |   570   (1)| 00:0
----------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   5 - filter("FUNCSWITCH"<>2 AND "EVLAN" IS NULL AND "DEVICEID"='DEV005M0')

//Eighteen rows have been selected.

SQL> 

Look at the predicate filtering condition with ID 5, all three of which occur on the view view.

3. Use trim or stitch an empty character

select * from 
(    select trim(deviceid) deviceid, port, cvlan, status, funcswitch, 
            decode(funcswitch, 3, pvlan, 1, pvlan) svlan,
            decode(funcswitch, 3, pvlan, 1, 
            lead(pvlan)over(partition by deviceid, port, cvlan, status order by pvlan asc)) evlan
     from   vlanstatus_pre2bak
)
where  funcswitch <> 2 and evlan is null and  deviceid = 'DEV005M0' ;

View the implementation plan:

SQL> set lines 200
SQL> set lines 300
SQL> set pages 200
SQL> explain plan for 
  2  select * from 
  3  (    select trim(deviceid) deviceid, port, cvlan, status, funcswitch, 
  4              decode(funcswitch, 3, pvlan, 1, pvlan) svlan,
  5              decode(funcswitch, 3, pvlan, 1, 
  6              lead(pvlan)over(partition by deviceid, port, cvlan, status order by pvlan asc)) evlan
  7       from   vlanstatus_pre2bak
  8  ) 
  9  where  funcswitch <> 2 and evlan is null and  deviceid = 'DEV005M0';

//It has been explained.

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
Plan hash value: 2175325539

--------------------------------------------------------------------------------------------------
| Id  | Operation           | Name               | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |                    |   313K|   209M|       |  4492   (1)| 00:00:54 |
|*  1 |  VIEW               |                    |   313K|   209M|       |  4492   (1)| 00:00:54 |
|   2 |   WINDOW SORT       |                    |   313K|    14M|    20M|  4492   (1)| 00:00:54 |
|   3 |    TABLE ACCESS FULL| VLANSTATUS_PRE2BAK |   313K|    14M|       |   690   (1)| 00:00:09 |
--------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("FUNCSWITCH"<>2 AND "EVLAN" IS NULL AND "DEVICEID"='DEV005M0')

//Fifteen rows have been selected.

SQL> 

View predicate filtering, all three filtering conditions occur on view with ID 1.
Small crab

Posted by russlock on Mon, 30 Sep 2019 06:39:37 -0700