oracle-databasejoinviewaggregatematerialized

Create an oracle materialized view with fast refresh on aggregated join


I've got this really nasty view that I'm trying to make faster by performing some joins ahead of time via materialized views. My problem is the most expensive joins, and therefore most worthwhile to pre-execute, don't play nice with materialized views.

Goal of the application is to provide livest data possible, so if I make mat views, they need to fast refresh on commit(maybe I haven't considered other approaches I'm unaware of). Fast refresh has limitations, specifically you must have rowid. See this thread here; but my problem is a little different as the nature of my join requires me to aggregate my join to get the right record.

Here's what I want to "pre-execute" (or optimize another genius way):

     CREATE MATERIALIZED VIEW testing
     NO LOGGING
     CACHE
     BUILD IMMEDIATE
     REFRESH FAST ON COMMIT 
     AS
       SELECT br.id, br.rowid, max(mr.id) as modifier_id --somehow fit mr.rowid in here
        FROM tableA br --base record
        LEFT OUTER JOIN tableA mr --modifier record
            ON br.external_key = mr.external_key
            AND mr.record_type_code in ('SOME','TYPE')
            AND mr.status_code in ('SOME','STATUS');

Basically, it's a self-join, because 0-*n* modifications get made to the entity, all of which are done in subsequent rows in the same table. I'm selecting the most recent of a given type. (I do this additional times for other types). To get the above working, I'd have to include rowid of both br and mr, which I can't wrap my brain around a way to do. I've considered rank() and ROWNUM instead of aggregating w/ MAX(), but can't get the logic right.

EDIT: Not sure fast refresh MV is in the cards for me as even if I make the refresh on demand and remove the aggregation entirely (assume there is exactly 1 row), oracle tells me the query is too complex for a fast refresh. So, now I'm in need of other ideas...


Solution

  • It might not be applicable in your situation, but possibly you could denormalize your table.

    For example, if you have multiple language dependent names, you could just have named columns for each language.

    For example, if your access is index-based, consider varray or nested tables.

    Another idea is to use triggers: On insert/update/delete, update another table (or tables), and use that table for the query. Possibly you can pre-calculate aggregates this way as well.