0

I have a Oracle 12c query that will eventually be used in a BIRT report (in IBM's Maximo Asset Management platform).


The query/report will retrieve records as follows:

  1. Retrieve workorders based on the parameters that were selected by the user.
    • All of the parameters are optional.
    • For testing purposes, I'm using bind variables as parameters (in Toad for Oracle).
    • It doesn't matter if the workorders are parents, children, or neither.
  2. Of the workorders that were retrieved, also select any children of those workorders.
    • There are only two levels to the parent/child hierarchy: parents and children (no grandchildren, etc.)

The output looks like this:

enter image description here

The blue boxes show examples of parents with children.


The query:

--short form definitions:
--wo   = workorder
--act  = actual (actual cost, actual date, etc.)
--pmtr = parameters

with 
wo_pmtr as (  --WOs filtered by parameters
select
    wonum,
    parent,
    hierarchypath,
    classstructureid,
    division,
    worktype,
    status, 
    trunc(actstart)  as actstart,
    trunc(actfinish) as actfinish,
    actlabcost,
    actmatcost,
    actservcost,
    acttoolcost,
    acttotalcost   
from
    workorder wo
where   
    --using bind variables as parameters in Toad
        (:wonum            is null     or wonum             = :wonum)
    and (:division         is null     or division          = :division)
    and (:worktype         is null     or worktype          = :worktype)
    and (:status           is null     or status            = :status)
    and (:actstart         is null     or trunc(actstart)  >= :actstart)
    and (:actfinish        is null     or trunc(actfinish) <= :actfinish)

    --retrieve workorders where the classification matches the parameter 
    --and retrieve any child classifications too
    --the classification hierarchy is not to be confused with the workorder hierarchy

    and (:classstructureid is null     or (exists (select 1 from classancestor where ((ancestor = :classstructureid)) and (classstructureid=wo.classstructureid))))
)

select
    wo_pmtr.wonum,
    wo_pmtr.parent,
    wo_pmtr.hierarchypath,
    wo_pmtr.classstructureid,
    wo_pmtr.division,
    wo_pmtr.worktype,
    wo_pmtr.status, 
    wo_pmtr.actstart,
    wo_pmtr.actfinish,
    wo_pmtr.actlabcost,
    wo_pmtr.actmatcost,
    wo_pmtr.actservcost,
    wo_pmtr.acttoolcost,
    wo_pmtr.acttotalcost,
    coalesce(wo_pmtr.parent, wo_pmtr.wonum) parent_coalesced
from
    wo_pmtr      --WOs filtered by parameters
union            --union will remove duplicates (unlike union all)
select           --select children of the filtered WOs
    wo.wonum,
    wo.parent,
    wo.hierarchypath,
    wo.classstructureid,
    wo.division,
    wo.worktype,
    wo.status, 
    trunc(wo.actstart)  as actstart,
    trunc(wo.actfinish) as actfinish,
    wo.actlabcost,
    wo.actmatcost,
    wo.actservcost,
    wo.acttoolcost,
    wo.acttotalcost,
    coalesce(wo.parent, wo.wonum) parent_coalesced
from
    workorder wo  --select from the base workorder table *without* filtering by the parameters
left join
    wo_pmtr
    on wo.parent = wo_pmtr.wonum
where
    wo.parent         is not null  --where WO is a child
    and wo_pmtr.wonum is not null  --where WO is a child of the filtered WOs 
                                   --caution: some of those workorders might have already been selected via the parameters in the first query
                                   --we need to eliminate duplicates if they exist (via the union)
order by
    parent_coalesced, 
    hierarchypath

db<>fiddle here


Question:

The query makes several full table scans:

enter image description here

Is there a way to reduce the number of full table scans to improve performance?

User1974
  • 276
  • 1
  • 17
  • 63
  • There is too much and not enough in this question. There is a wall of detail, however, all the basic building blocks that might allow someone to put together a meaningful answer are missing as there is no [MRE]. Please [edit] your question to include the DDL statements necessary to build the tables needed for your query and the DML statements for some sample data and what your expected output would be for that sample data along with an explanation (in English, and not code) of what you are trying to achieve with the code. – MT0 Nov 15 '20 at 22:17
  • Have you tried using a hierarchical query to solve this rather than querying the same table multiple times at different levels of the hierarchy and then relyin on `UNION` and self joins. – MT0 Nov 15 '20 at 22:21
  • Pardon my ignorance, but does the dbfiddle and the screenshot of the output not provide the kind of information that is needed? I actually wanted to delete the question, but I can't because it has been flagged by another post as a duplicate. – User1974 Nov 15 '20 at 22:27
  • My bad, I couldn't see the db<>fiddle as it is buried in the middle of a very dense question and you've put it in superscript font so it is tiny. The question is still lacking a description of what the query is trying to achieve. A brief look makes it seem like you should be able to use a hierarchical query to achieve this in a single table scan but I'm not sure I understand what you want to achieve to be able to answer. – MT0 Nov 15 '20 at 22:37
  • Please learn how to post the execution plan in a **text from** e.g. [here](https://stackoverflow.com/a/34975420/4808122) – Marmite Bomber Nov 15 '20 at 22:56

2 Answers2

1

There are many indexes that you can use on the WORKORDER table. What stands out in your query is that you're not referring to the SITEID column which should almost always come with the WONUM as together they compose the "primary key", which in Oracle Maximo is a unique index.

You can confirm this by running this query:

   select attributename from maxattribute where objectname='WORKORDER' AND PRIMARYKEYCOLSEQ IS NOT NULL;

Also, a good practice is to identify which indexes you will need to query the needed data. You can have a look at the table's indexes with your favorite SQL tool or from the Database Configuration Maximo application.

JPTremblay
  • 900
  • 5
  • 8
0

full table scans are only required if no proper index is in place. So create such and you will see that the full table scans disappear

cboden
  • 813
  • 9
  • 14
  • What would you suggest as a proper index in this case? I can see no filter that would use an index without a bit of rewrite help. – Andrew Sayer Nov 16 '20 at 08:29