Using Essbase as an Aggregation Layer for Federated OBIEE Models
Now that the 11.1 release of Essbase is out, together with Essbase Studio, an option that's now open to us is to use Essbase as an aggregation layer for OBIEE. You can build a single logical dimensional model over your data using the Oracle BI Administrator tool, source your data from a number of relational databases using the "federated query" feature, load a summarized version of it into Essbase and then plug the Essbase cube back into OBIEE to provide aggregations. In theory it's quite a neat feature, and one that Oracle plan to include in the next release of OBIEE as an automated feature, but how does it work now and are there any areas to watch out for, particularly when we have complex federated logical models in OBIEE that have measures of differing granularity?
To take an example, I've got a logical OBIEE model that takes its data from relational and excel data sources. This is the model I went through in this article and use for most of my demonstrations, together with this additional data source that maps quota data in at a different level of granularity.
Essbase, unlike Oracle OLAP, has the concept of "hypercubes" where every measure within a cube is dimensioned by every dimension. This is similar to how a relational fact table works, but is different to Oracle OLAP which uses Analytic Workspaces, collections of measures and dimensions where each measure can be associated with any arbitrary selection of dimensions. The nearest equivalent to an Essbase hypercube in Oracle OLAP is an Oracle OLAP "cube", which is actually where you bring dimensions and measures together and is used mainly be legacy Oracle OLAP query tools such as Discoverer for OLAP. But overall, Oracle OLAP is a bit more flexible when it comes to measure dimensionality, and so if we're going to use Essbase then we need to think about how we're going to design this.
In fact, there are two main approaches we can take:
-
If we want a single Essbase cube, then we can only do what we've done in Answers and create the cube where the dimensions and granularity are common between the two data sources; that is, we create two measures, quota and quantity, and dimension them by product (going from category up to all products) and time (going from month up to quarter, year and all times). This isn't bad, but it doesn't provide any aggregation for the quantity measure when we analyze it by the customer dimension.
-
We can create a separate Essbase cube (or "database") for each measure, we can then dimension each of these as per the original data source, but then we are going to have two Essbase data sources for OBIEE and it's potentially going to get a bit complicated.
Having said all of this, if your OBIEE model has just a single data source then things will be a lot simpler, you'll just use Essbase Studio to create an aggegated cube in Essbase and then plug it back into OBIEE. But to start off, let's look at the first scenario, where we do indeed stick with a single Essbase cube and just use it to aggregate the OBIEE data where there is shared dimensionality.
Bringing the OBIEE "tables" into Essbase Studio and creating an initial MiniSchema diagram, you can see how the four tables are joined and that they are joined on the lowest level of detail:
-------------------- Logical Request (before navigation):So what happens if we run a report that includes the customer dimension in the report, or requests data at a finer level of granularity than the cube contains, such as if we drill-down on the category to show the individual products? In either case, the BI Server switches over to the relational source that provides more detailed data for the quantity measure, CASTing the quota measure as NULL so that it shows as a blank in report.RqList
Product.Category as c1 GB,
Quantity:[DAggr(Items.Quantity by [ Product.Category] )] as c2 GB
OrderBy: c1 asc+++Administrator:6b0000:6b0006:----2009/03/05 14:43:20
-------------------- Sending query to database named w2k3vm (id: <<30675>>):
With
set [ProductHier2] as '[ProductHier].Generations(2).members'
select
{ [MeasureHier].[Quantity]
} on columns,
NON EMPTY {{[ProductHier2]}} properties ANCESTOR_NAMES, GEN_NUMBER on rows
from [CusApp.CubeFull]
-------------------- Logical Request (before navigation): RqList Product.Category as c1 GB, Product.Product ID as c2 GB, Quantity:[DAggr(Items.Quantity by [ Product.Category, Product.Product ID] )] as c3 GB, Quota:[DAggr(Items.Quota by [ Product.Category, Product.Product ID] )] as c4 GB DetailFilter: Product.Category = 'Computers' OrderBy: c1 asc, c2 asc +++Administrator:6b0000:6b0009:----2009/03/05 14:55:50 -------------------- Sending query to database named orcl (id: >): select distinct D1.c2 as c1, D1.c3 as c2, D1.c1 as c3, cast(NULL as DOUBLE PRECISION ) as c4 from (select sum(T3102.QUANTITY) as c1, T3118.CATEGORY as c2, T3118.PRODID as c3 from CUST_ORDER_HISTORY.PRODUCT T3118, CUST_ORDER_HISTORY.ITEMS T3102 where ( T3102.PRODID = T3118.PRODID and T3118.CATEGORY = 'Computers' ) group by T3118.CATEGORY, T3118.PRODID ) D1 order by c1, c2But what if we want to view just quantity data aggregated, with the customer dimension included? The cube we've just built in Essbase excludes the customer dimension as the quota measure isn't dimensioned by it, so in this case the BI Server would have to revert back to aggregating the detail-level relational data for this measure. What we can do though is create another Essbase cube but this time just for the quantity measure, again loaded with aggregated data but with the full set of dimensions attached, like this:
-------------------- Logical Request (before navigation): RqList Product.Category as c1 GB, Times.Year as c2 GB, Quantity:[DAggr(Items.Quantity by [ Customer.State, Product.Category, Times.Year] )] as c3 GB, Customer.State as c4 GB OrderBy: c1 asc, c2 asc, c4 asc +++Administrator:850000:85000a:----2009/03/05 16:30:05 -------------------- Sending query to database named w2k3vm (id: <<36589>>): With set [CustHier3] as '[CustHier].Generations(3).members' set [ProductHier2] as '[ProductHier].Generations(2).members' set [TimeHier2] as '[TimeHier].Generations(2).members' select { [QuantHier].[Quantity] } on columns, NON EMPTY {crossjoin ({[CustHier3]},crossjoin ({[ProductHier2]},{[TimeHier2]}))} properties ANCESTOR_NAMES, GEN_NUMBER on rows from [CusApp2.CubeQuan]If you then add the quota measure into the query, the BI Server still queries the same Essbase dataset but doesn't return any quota information, but if you then leave quota in but remove the dimension that only the quantity measure uses, the BI Server switches over to the Essbase cube that provides data for both of the measures.
So, the moral of the story is: it's relatively simple to take data in your OBIEE logical model, load it into an Essbase cube and then map it back into OBIEE. Essbase can therefore provide an easy-to-setup aggregation layer for OBIEE that satisfies all of your aggregations, not just the individual ones that the existing Aggregate Persistence Wizard does (Oracle OLAP does a good job on this, as well). If your logical model is a bit more complex though, and in particular features measures that contain values only at certain levels of granularity, you will need to set up multiple Essbase cubes (or "databases") and map them in to each measure appropriately. It's not a particularly big deal, and the BI Server hands-off between the different Essbase data sources well, but it something that you'll need to think about if you start using Essbase to aggregate OBIEE logical model that feature federated data sources and/or measures of differing granularity.