1

In the process of migrating our DB from Oracle 11 to Oracle 12c (12.2.0.1.0), we discovered that the same query gives different results on the two instances.

The query is:

VARIABLE myId NUMBER;
BEGIN :myId := 1325; END;
/

SELECT
  rid, ora_rowscn
FROM
  my_table
WHERE
  rid = NVL(:myId, rid);

On Oracle 11, we have:

      RID ORA_ROWSCN
--------- ----------
     1325 1.3439E+13
     1325 1.3439E+13

while on Oracle 12c we have:

      RID ORA_ROWSCN
--------- ----------
     1325
     1325

and the following query

SELECT
  rid, ora_rowscn
FROM
  my_table
WHERE
  rid = NVL(1325, rid);

gives:

      RID ORA_ROWSCN
--------- ----------
     1325    2549788
     1325    2549788

(Clearly the different values of the ORA_ROWSCN column are expected.)

MY_TABLE.RID is NUMBER(38) NOT NULL and there is a non-unique index on it.

I strongly suspect that the wrong results are the unintended consequences of the optimizer, but, as I have a very limited experience with DBs, I have no clues on how to fix this strange behavior.

The execution plans of the two queries are:

Plan hash value: 709374914

---------------------------------------------------------------------------------------
| Id  | Operation           | Name            | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |                 |    52 |   676 |     2   (0)| 00:00:01 |
|   1 |  VIEW               | VW_ORE_55EECC8D |    52 |   676 |     2   (0)| 00:00:01 |
|   2 |   UNION-ALL         |                 |       |       |            |          |
|*  3 |    FILTER           |                 |       |       |            |          |
|*  4 |     INDEX RANGE SCAN| MY_TABLE_INDEX1 |     1 |    13 |     1   (0)| 00:00:01 |
|*  5 |    FILTER           |                 |       |       |            |          |
|   6 |     INDEX FULL SCAN | MY_TABLE_INDEX1 |    51 |   663 |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------------------

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

   3 - filter(:MYID IS NOT NULL)
   4 - access("RID"=:MYID)
   5 - filter(:MYID IS NULL)

Note
-----
   - dynamic statistics used: dynamic sampling (level=2)

and

Plan hash value: 460232730

-------------------------------------------------------------------------------------------------------
| Id  | Operation                           | Name            | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                    |                 |     2 |    26 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID BATCHED| MY_TABLE        |     2 |    26 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN                  | MY_TABLE_INDEX1 |     2 |       |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------------

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

   2 - access("RID"=1325)

Note
-----
   - dynamic statistics used: dynamic sampling (level=2)

My question is: how can I obtain on Oracle 12c the same results that I obtained so far on Oracle 11?

4
  • odd. What is your 12c patchset? (please post the result of select * from v$version;) Commented Jul 20, 2018 at 13:46
  • What's the definition of my_table? Specifically the data type of the RID column? Commented Jul 20, 2018 at 20:16
  • The query with the bind variable may be using a different execution plan from the one with the hardcoded value. Posting the plans may give a clue.
    – Gary
    Commented Jul 23, 2018 at 3:28
  • Thanks for your interest. I updated the text accordingly. Commented Jul 23, 2018 at 6:55

1 Answer 1

0

The plan clearly shows the OR-expansion query transformation. It is not the first time it produced wrong results due to various bugs.

Try running your query as:

SELECT /*+ NO_EXPAND */
  rid, ora_rowscn
FROM
  my_table
WHERE
  rid = NVL(:myId, rid);

Or set the below parameters before executing it:

alter session set "_no_or_expansion"=true;
alter session set "_or_expand_nvl_predicate"=false;

Then run your query.

2
  • Thanks. Both the optimization hint and each one of the alter session statements "solve" the issue. Changing each query would be unpractical. Could you please suggest which alter session statement should I use? Commented Jul 23, 2018 at 8:49
  • @user1366204 I suggest using the second one (alter session set "_or_expand_nvl_predicate"=false;), because OR-expansion works with OR predicates without NVL as well, while this parameter disables OR-expansion only for NVL predicates. Btw, I tested it on 12.2.0.1.180717 and 18.2, and I could reproduce the issue in both versions, it is still not fixed. Commented Jul 23, 2018 at 9:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.