Recently I came across an issue with usage of + operator(Basically Right Outer Join in my case) along with NVL .
Basically when we use NVL , DB2 internally uses COALESCE function (We can make it out by looking at explain plan).
But when it is used along with + Join operator , the explain plan shows that NVL function is internally not able to call COALESCE function.
Example :
--------------------------------------------------------------------------------
Original Query in Oracle ( Which does not give required output in DB2
--------------------------------------------------------------------------------
select rps_obj.object_name, rps_rel.CHILD_OBJ_ID, NVL(rps_rel.CHILD_OBJ_ID, 0), rps_rel.PARENT_OBJ_ID, NVL(rps_rel.PARENT_OBJ_ID, 0), rps_res.OBJECT_ID
from RPS_OBJECTS rps_obj,
(select * from RPS_OBJ_DEPENDENCIES where DEPENDS_ON in (select OBJECT_ID from RPS_OBJECTS where OBJECT_CATEGORY = 'Compliance Objects')) rps_dpnd_res,
RPS_RESOURCE_OBJECTS rps_res,
RPS_OBJECTS rps_obj_res,
ASSETTYPES at,
(select * from RPS_OBJ_DEPENDENCIES where DEPENDS_ON in (select OBJECT_ID from RPS_OBJECTS where OBJECT_CATEGORY = 'Compliance Object Relations')) rps_dpnd_rel,
RPS_RELATIONS rps_rel,
RPS_OBJECTS rps_obj_rel
where rps_obj.OBJECT_CATEGORY = 'Compliance Object Views'
and rps_obj.OBJECT_TYPE = 'VIEW'
and rps_obj.OBJECT_ID = NVL(38, rps_obj.OBJECT_ID)
and rps_dpnd_res.OBJECT_ID = rps_obj.OBJECT_ID
and rps_res.OBJECT_ID = rps_dpnd_res.DEPENDS_ON
and rps_obj_res.OBJECT_ID = rps_res.OBJECT_ID and rps_obj_res.OBJECT_CATEGORY = 'Compliance Objects'
and at.ASSETTYPEID = rps_res.CONTENT_TYPE
and rps_dpnd_rel.OBJECT_ID (+) = rps_obj.OBJECT_ID
and rps_rel.OBJECT_ID (+) = rps_dpnd_rel.DEPENDS_ON
and rps_obj_rel.OBJECT_ID (+) = rps_rel.OBJECT_ID and rps_obj_rel.OBJECT_CATEGORY (+) = 'Compliance Object Relations'
and NVL(rps_rel.CHILD_OBJ_ID, 0) = NVL(rps_rel.PARENT_OBJ_ID, 0)
and NVL(rps_rel.CHILD_OBJ_ID, rps_res.OBJECT_ID) = rps_res.OBJECT_ID
-------------------------------------------------------------------------------------------------
There are two possible solution to this
-------------------------------------------------------------------------------------------------
Solution 1 ) Simplify the NVL function.
Change the following piece of code
and NVL(rps_rel.CHILD_OBJ_ID, 0) = NVL(rps_rel.PARENT_OBJ_ID, 0)
and NVL(rps_rel.CHILD_OBJ_ID, rps_res.OBJECT_ID) = rps_res.OBJECT_ID
To following :
-- and (rps_rel.CHILD_OBJ_ID = rps_rel.PARENT_OBJ_ID or (rps_rel.CHILD_OBJ_ID is NULL and rps_rel.PARENT_OBJ_ID is NULL))
-- and (rps_rel.CHILD_OBJ_ID is NULL or rps_rel.CHILD_OBJ_ID = rps_res.OBJECT_ID)
------------------------------------------------------------------------------------------------------------------------------
Solution 2 : Rewrite the complete query following ANSI standard
------------------------------------------------------------------------------------------------------------------------------
Modified query :
select rps_obj.object_name, rps_rel.CHILD_OBJ_ID, NVL(rps_rel.CHILD_OBJ_ID, 0), rps_rel.PARENT_OBJ_ID, NVL(rps_rel.PARENT_OBJ_ID, 0), rps_res.OBJECT_ID
from RPS_RESOURCE_OBJECTS rps_res, RPS_OBJECTS rps_obj_res, ASSETTYPES at,
(select * from RPS_OBJ_DEPENDENCIES where DEPENDS_ON in (select OBJECT_ID from RPS_OBJECTS where OBJECT_CATEGORY = 'Compliance Objects')) rps_dpnd_res,
RPS_OBJECTS rps_obj_rel RIGHT OUTER JOIN RPS_RELATIONS rps_rel ON rps_obj_rel.OBJECT_ID = rps_rel.OBJECT_ID AND rps_obj_rel.OBJECT_CATEGORY = 'Compliance Object Relations'
RIGHT OUTER JOIN (select * from RPS_OBJ_DEPENDENCIES where DEPENDS_ON in (select OBJECT_ID from RPS_OBJECTS where OBJECT_CATEGORY = 'Compliance Object Relations')) rps_dpnd_rel ON rps_rel.OBJECT_ID = rps_dpnd_rel.DEPENDS_ON
RIGHT OUTER JOIN RPS_OBJECTS rps_obj ON rps_dpnd_rel.OBJECT_ID = rps_obj.OBJECT_ID
where rps_obj.OBJECT_CATEGORY = 'Compliance Object Views'
and rps_obj.OBJECT_TYPE = 'VIEW'
and rps_obj.OBJECT_ID = NVL(38, rps_obj.OBJECT_ID)
and rps_dpnd_res.OBJECT_ID = rps_obj.OBJECT_ID
and rps_res.OBJECT_ID = rps_dpnd_res.DEPENDS_ON
and rps_obj_res.OBJECT_ID = rps_res.OBJECT_ID and rps_obj_res.OBJECT_CATEGORY = 'Compliance Objects'
and at.ASSETTYPEID = rps_res.CONTENT_TYPE
and NVL(rps_rel.CHILD_OBJ_ID, 0) = NVL(rps_rel.PARENT_OBJ_ID, 0)
and NVL(rps_rel.CHILD_OBJ_ID, rps_res.OBJECT_ID) = rps_res.OBJECT_ID
Note : This issue has been fixed in v97fp6 now. So upgrade your instance to v97fp6
Basically when we use NVL , DB2 internally uses COALESCE function (We can make it out by looking at explain plan).
But when it is used along with + Join operator , the explain plan shows that NVL function is internally not able to call COALESCE function.
Example :
--------------------------------------------------------------------------------
Original Query in Oracle ( Which does not give required output in DB2
--------------------------------------------------------------------------------
select rps_obj.object_name, rps_rel.CHILD_OBJ_ID, NVL(rps_rel.CHILD_OBJ_ID, 0), rps_rel.PARENT_OBJ_ID, NVL(rps_rel.PARENT_OBJ_ID, 0), rps_res.OBJECT_ID
from RPS_OBJECTS rps_obj,
(select * from RPS_OBJ_DEPENDENCIES where DEPENDS_ON in (select OBJECT_ID from RPS_OBJECTS where OBJECT_CATEGORY = 'Compliance Objects')) rps_dpnd_res,
RPS_RESOURCE_OBJECTS rps_res,
RPS_OBJECTS rps_obj_res,
ASSETTYPES at,
(select * from RPS_OBJ_DEPENDENCIES where DEPENDS_ON in (select OBJECT_ID from RPS_OBJECTS where OBJECT_CATEGORY = 'Compliance Object Relations')) rps_dpnd_rel,
RPS_RELATIONS rps_rel,
RPS_OBJECTS rps_obj_rel
where rps_obj.OBJECT_CATEGORY = 'Compliance Object Views'
and rps_obj.OBJECT_TYPE = 'VIEW'
and rps_obj.OBJECT_ID = NVL(38, rps_obj.OBJECT_ID)
and rps_dpnd_res.OBJECT_ID = rps_obj.OBJECT_ID
and rps_res.OBJECT_ID = rps_dpnd_res.DEPENDS_ON
and rps_obj_res.OBJECT_ID = rps_res.OBJECT_ID and rps_obj_res.OBJECT_CATEGORY = 'Compliance Objects'
and at.ASSETTYPEID = rps_res.CONTENT_TYPE
and rps_dpnd_rel.OBJECT_ID (+) = rps_obj.OBJECT_ID
and rps_rel.OBJECT_ID (+) = rps_dpnd_rel.DEPENDS_ON
and rps_obj_rel.OBJECT_ID (+) = rps_rel.OBJECT_ID and rps_obj_rel.OBJECT_CATEGORY (+) = 'Compliance Object Relations'
and NVL(rps_rel.CHILD_OBJ_ID, 0) = NVL(rps_rel.PARENT_OBJ_ID, 0)
and NVL(rps_rel.CHILD_OBJ_ID, rps_res.OBJECT_ID) = rps_res.OBJECT_ID
-------------------------------------------------------------------------------------------------
There are two possible solution to this
-------------------------------------------------------------------------------------------------
Solution 1 ) Simplify the NVL function.
Change the following piece of code
and NVL(rps_rel.CHILD_OBJ_ID, 0) = NVL(rps_rel.PARENT_OBJ_ID, 0)
and NVL(rps_rel.CHILD_OBJ_ID, rps_res.OBJECT_ID) = rps_res.OBJECT_ID
To following :
-- and (rps_rel.CHILD_OBJ_ID = rps_rel.PARENT_OBJ_ID or (rps_rel.CHILD_OBJ_ID is NULL and rps_rel.PARENT_OBJ_ID is NULL))
-- and (rps_rel.CHILD_OBJ_ID is NULL or rps_rel.CHILD_OBJ_ID = rps_res.OBJECT_ID)
------------------------------------------------------------------------------------------------------------------------------
Solution 2 : Rewrite the complete query following ANSI standard
------------------------------------------------------------------------------------------------------------------------------
Modified query :
select rps_obj.object_name, rps_rel.CHILD_OBJ_ID, NVL(rps_rel.CHILD_OBJ_ID, 0), rps_rel.PARENT_OBJ_ID, NVL(rps_rel.PARENT_OBJ_ID, 0), rps_res.OBJECT_ID
from RPS_RESOURCE_OBJECTS rps_res, RPS_OBJECTS rps_obj_res, ASSETTYPES at,
(select * from RPS_OBJ_DEPENDENCIES where DEPENDS_ON in (select OBJECT_ID from RPS_OBJECTS where OBJECT_CATEGORY = 'Compliance Objects')) rps_dpnd_res,
RPS_OBJECTS rps_obj_rel RIGHT OUTER JOIN RPS_RELATIONS rps_rel ON rps_obj_rel.OBJECT_ID = rps_rel.OBJECT_ID AND rps_obj_rel.OBJECT_CATEGORY = 'Compliance Object Relations'
RIGHT OUTER JOIN (select * from RPS_OBJ_DEPENDENCIES where DEPENDS_ON in (select OBJECT_ID from RPS_OBJECTS where OBJECT_CATEGORY = 'Compliance Object Relations')) rps_dpnd_rel ON rps_rel.OBJECT_ID = rps_dpnd_rel.DEPENDS_ON
RIGHT OUTER JOIN RPS_OBJECTS rps_obj ON rps_dpnd_rel.OBJECT_ID = rps_obj.OBJECT_ID
where rps_obj.OBJECT_CATEGORY = 'Compliance Object Views'
and rps_obj.OBJECT_TYPE = 'VIEW'
and rps_obj.OBJECT_ID = NVL(38, rps_obj.OBJECT_ID)
and rps_dpnd_res.OBJECT_ID = rps_obj.OBJECT_ID
and rps_res.OBJECT_ID = rps_dpnd_res.DEPENDS_ON
and rps_obj_res.OBJECT_ID = rps_res.OBJECT_ID and rps_obj_res.OBJECT_CATEGORY = 'Compliance Objects'
and at.ASSETTYPEID = rps_res.CONTENT_TYPE
and NVL(rps_rel.CHILD_OBJ_ID, 0) = NVL(rps_rel.PARENT_OBJ_ID, 0)
and NVL(rps_rel.CHILD_OBJ_ID, rps_res.OBJECT_ID) = rps_res.OBJECT_ID
Note : This issue has been fixed in v97fp6 now. So upgrade your instance to v97fp6
No comments:
Post a Comment