Dimension Data Mart Development 

Data Mart development of a dimension means creating a (snapshot) table with calculated/derived information. There are two different Data Mart source types; one based on Materialized Views and one based on an ordinary table supported by incremental load.

This page deals with the source type Materialized Views. Data Mart development based on incremental load is found on a separate page named Incremental Load Development, valid both for dimensions and facts.

Materialized Views access means that a Materialized View in the Oracle database is created that serves as place holders for all, or at least most part of, the information associated with a dimension. To publish the data in the Materialized Views, a dimension view has to be defined and then IFS Business Reporting & Analysis services specific Metadata for the dimension must be defined and deployed.

This section provides some of the basic steps needed to create Meta Data support for a dimension.

Note: A dimension should as far as possible always support both Online and Data Mart access. For more details about Online implementation please refer to the Online development page.

Note: All development of dimension entities in IFS Applications should be done by using the IFS Developer Studio. The development is model based. Compared to a LU entity, a dimension entity has a model file as well as generated files in the code repository. This is important to remember - never edit the dimension files manually, instead always use the model.
For more information about how to handle modeling of a dimension, please refer to IFS Develop Studio but also to the section about modeling.
The current page provides some details, things that can be good to know when developing a dimension entity.

 

Contents

General MV Definition

A Materialized View (MV) is a snapshot table that is created from a SELECT statement. When creating a MV for a dimension, this is done by creating a PL/SQL block where the SELECT statement is executed dynamically. The block also contains creation of indexes.

The Materialized View has the following structure:

DECLARE
   stmt_                    VARCHAR2(32000);
   columns_                 Database_SYS.ColumnTabType;
   table_name_              VARCHAR2(30) := '&MV';
   index_name_              VARCHAR2(30);
   constraint_name_         VARCHAR2(30);
BEGIN

   dbms_output.put_line('Primary key cascade drop ON &MV');
   Database_SYS.Remove_All_Cons_And_Idx('&MV', TRUE);
   
   dbms_output.put_line('Drop Materialized View &MV');
   Database_SYS.Remove_Materialized_View('&MV', TRUE);

   dbms_output.put_line('Create Materialized View &MV');
   stmt_ :=
   'CREATE MATERIALIZED VIEW &MV 
    TABLESPACE &IFSAPP_DATA
    BUILD DEFERRED
    USING NO INDEX
    REFRESH COMPLETE ON DEMAND
    AS 
    SELECT 
     -- ID (unique identity) column
           <parent1_column>||''^''||...||<parentN_column>||''^''||<key_column>  id,
     -- parent columns
           <parent1_column>                                                     <parent1_column_alias>,
           ...                                                                  ...,
           <parentN_column>                                                     <parentN_column_alias>,         
     -- key (CODE) column                                                      
           <key_column>                                                         code,
     -- other attributes                                                       
           <attribute1_column>                                                  <attribute1_column_alias>,
           ...                                                                  ...,
           <attributeN_column>                                                  <attributeN_column_alias>
    FROM <source_table> 
    WHERE <source_condition>
    UNION ALL
    SELECT <parent1_column>||''^''||...||<parentN_column>||''^''||''#''         id,
           <parent1_column>                                                     <parent1_column_alias>,
           ...                                                                  ...,
           <parentN_column>                                                     <parentN_column_alias>, 
           NULL                                                                 code,
           NULL                                                                 <attribute1_column_alias>,
           ...                                                                  ...,
           NULL                                                                 <attributeN_column_alias>
    FROM <parentN_table>
    WHERE <parentN_condition>
    UNION ALL
     ...
    UNION ALL
    SELECT <parent1_column>||''^''||...||''#''||''^''||''#''                    id,
           <parent1_column>                                                     <parent1_column_alias>,
           ...                                                                  ...,
           NULL                                                                 <parentN_column_alias>, 
           NULL                                                                 code,
           NULL                                                                 <attribute1_column_alias>,
           ...                                                                  ...,
           NULL                                                                 <attributeN_column_alias>
    FROM <parent1_table>
    WHERE <parent1_condition>
    UNION ALL
    SELECT ''#''||''^''||...||''#''||''^''||''#''                               id,
           NULL                                                                 <parent1_column_alias>,
           ...                                                                  ...,
           NULL                                                                 <parentN_column_alias>, 
           NULL                                                                 code,
           NULL                                                                 <attribute1_column_alias>,
           ...                                                                  ...,
           NULL                                                                 <attributeN_column_alias>
    FROM BI_DUAL_TAB';

   EXECUTE IMMEDIATE stmt_;

   dbms_output.put_line('Create constraints and indexes on Materialized View &MV');
   
   constraint_name_ := table_name_ || '_PK';
   Database_SYS.Set_Table_Column (columns_ , 'ID');
   Database_Sys.Create_Constraint(table_name_,
                                  constraint_name_,
                                  columns_,
                                  'P',
                                  '&XXXXXX_MVIEW_INDEX',
                                  NULL,
                                  TRUE,
                                  TRUE);
   Installation_SYS.Reset_Column_Table(columns_);

   index_name_ := table_name_||'_UX1';
   Database_SYS.Set_Table_Column (columns_ , '<parent1_column_alias>');
   ...
   Database_SYS.Set_Table_Column (columns_ , '<parentN_column_alias>');
   Database_SYS.Set_Table_Column (columns_ , 'CODE');
   Database_SYS.Create_Index ( table_name_,
                               index_name_,
                               columns_,
                               'U',
                               '&XXXXXX_MVIEW_INDEX',
                               NULL,
                               TRUE,
                               TRUE);
   Installation_SYS.Reset_Column_Table(columns_);
   
   index_name_ := table_name_ || '_IX1';
   Database_SYS.Set_Table_Column (columns_ , '<parent1_column_alias>');
   ...
   Database_SYS.Set_Table_Column (columns_ , '<parentN_column_alias>');
   Database_SYS.Set_Table_Column (columns_ , '<attribute1_column_alias>');
   Database_Sys.Create_Index( table_name_,
                              index_name_,
                              columns_,
                              'N',
                              '&XXXXXX_MVIEW_INDEX');
   Installation_SYS.Reset_Column_Table(columns_);
   
   ...

END;
/   

Some remarks:

Remarks

Some general remarks about Data Mart development for dimensions.

Note: All development is done in IFS Developer Studio where a dimension model is used

Performance Indexes

To get good performance when accessing an Information Source, using the Data Mart as source, it is important to create indexes on the Materialized Views representing dimension and fact data. Some recommendations:

Assume we have index definitions in the model:

indexinfo {
   indexes {
      index on columns AccountGroup,Company;
      index unique on columns Company,Code;
   }
}

IFS Developer Studio will create

Index names will be automatically generated.

Download and check the MV file MV_AccrulDimAccount.cre if needed.

 

Creating NULL Identities

Dimension specific Materialized Views should contain NULL identities, mentioned in the remarks section.

These NULL identities are normally created by performing an extra select from a typical parent table, to get one NULL identity row per each parent.

One example is supplied here, where we create a Materialized View representing accounts.

CREATE MATERIALIZED VIEW &MV 
TABLESPACE &ACCRUL_MVIEW_DATA
BUILD DEFERRED
USING NO INDEX
REFRESH COMPLETE ON DEMAND
AS
SELECT  a.company||'^'||a.code_part_value  id,
        a.company                          company,
        a.code_part_value                  code,
        a.description                      description,
        a.accnt_group                      account_group,
        a.accnt_type                       account_type
FROM ACCOUNTING_CODE_PART_VALUE_TAB a
WHERE a.code_part  = 'A'
UNION ALL 
SELECT  company || '^' || '#'              id, 
        company                            company,
        NULL                               code,
        NULL                               description,
        NULL                               account_group,
        NULL                               account_type
FROM COMPANY_FINANCE_TAB
UNION ALL
SELECT '#' || '^' || '#'                   id,
        NULL                               company,
        NULL                               code,
        NULL                               description,
        NULL                               account_group,
        NULL                               account_type
FROM BI_DUAL_TAB;

The ID column is created from two values, the COMPANY and the CODE, i.e. the parent key and the key. The CODE represents accounts. We can look at it as ID = (<parent_key>, <key>) = (COMPANY, CODE)

The select has three parts:

  1. The first part selects accounts from the natural dimension source table (ACCOUNTING_CODE_PART_VALUE_TAB).
  2. The second part considers the case where the key column CODE, i.e. account, is NULL. We should create one NULL row for each valid parent, company.

    This is done by adding a select from the parent table COMPANY_FINANCE_TAB.

    The ID is created as (COMPANY, '#'), i.e. we use the hash character to represent the NULL value of account/CODE.

  3. The third part considers the case where both the parent, COMPANY, and the key, CODE, are NULL. Even if we believe that there will always be a company in our Information Sources, we should make sure to cover this case anyway.

Choose the following SELECT values:

To select the single NULL record that represents the case when parents and keys are all NULL, please use the table BI_DUAL_TAB instead of the Oracle table DUAL. The reason is that if a Materialized View contains select from the DUAL table, it will not be possible for Oracle to track changes in other tables in the SELECT clause, so the Materialized Views can be marked as FRESH even if the source tables have changed. By using an ordinary table like BI_DUAL_TAB this problem is solved.

One example:

CREATE MATERIALIZED VIEW &MV 
TABLESPACE &IFSAPP_DATA
BUILD DEFERRED
USING NO INDEX
REFRESH COMPLETE ON DEMAND
AS
SELECT  a.column1                  id,
        a.column1                  code,
        a.description              description
FROM XYZ_TAB a
UNION ALL 
SELECT  '#'                        id, 
        ''                         code,
        ''                         description   
FROM BI_DUAL_TAB

The second part selects one line from BI_DUAL_TAB that will represent a NULL identity record.

Note: Do not use Oracle's DUAL table. Using it will lead to incorrect refresh status of the Materialized View.

To make things work when connecting the dimension to a fact it is important that the fact definition also handles the NULL values in the same way for the columns representing the dimension identities. But if for a specific fact, the key values of a dimension are always present on all transaction rows, then the fact definition for the dimension identity can be done without NULL value handling.

Deployment

Development of Data Mart support for a dimension means creating a set of files that have to be deployed in the database.

The files are:

  1. Materialized View file definition
  2. Dimension View file definition
  3. Dimension Metadata file

Materialized View File

The Materialized View definition is either represented as a CRE file, a UPG file or as a part of a CDB file (bug correction).

The file is deployed in the database as any other CRE/UPG/CDB file.

When the Materialized View has been created, it is important to find out how long time it will take to perform a complete refresh and of course also to make sure that the selected data is correct.

A Materialized View is always empty after creation and the staleness is UNUSABLE. The Materialized View has to be activated first, i.e. the first snapshot has to be created. The Materialized View features in IFS Solution Manager can normally be used for activation BUT these features are supposed to be used in an environment where all BI specific files have been deployed. So the suggested way to do the activation during development is to execute the following PL/SQL block in the database:

BEGIN
   Xlr_Mv_Util_API.Activate_Unusable_Mviews(<mview_name1>[,<mview_name2>,...,<mview_name3>]);
END;

After this step the natural thing would be to SELECT from the Materialized View to make sure that:

Testing refresh performance requires a large database.

The staleness (state) of a Materialized View can have many different values. Please refer to Materialized View Basics for more detailed information.

The Materialized View file can be downloaded if needed.

 

Dimension View File

The dimension view definition is represented as an APV file, meaning that it represents a public read interface.

The file is deployed in the database as any other CRE/UPG/CDB file.

After deployment the natural thing would be to SELECT from the view.

Make sure that:

Note: It is very important to refresh the F1 dictionary after having created a new dimension view that is supposed to act as List of Values view in IFS Reporting.

The Data mart access/view file DimAccountDm.apv can be downloaded if needed.

 

Metadata File

A dimension has to be described/defined in a Metadata file. The Metadata is represented as an INS file.

The file is deployed in the database as any other INS file.

There is of course also the possibility to create the dimension metadata in the Information Source feature.

Note: If the Information Source feature is used to create or add metadata, it is important to make sure to export the metadata to file as the last step. The reason is that any modification through the feature is a customization of the metadata in the current environment and if the changes are not reflected in a metadata file, it means that next time the metadata file is executed, all manual configuration will be lost.

Note: All development should preferably be made using IFS Developer Studio

Information about the deployment is output on screen (or in a log file). Errors must be investigated and corrected. Information lines should be looked up. Do one of the following:

  1. Open the Information Source log feature. This feature displays all log entries registered when deploying the metadata INS file or when doing manual metadata configuration.
  2. Perform the following SELECT
    SELECT * FROM XLR_IMPORT_LOG_TAB ORDER BY TIMESTAMP DESC

When the accurate IMPORT_ID has been found, the following SELECT can be performed:

SELECT * FROM XLR_IMPORT_LOG_TAB WHERE IMPORT_ID = '<import_id>' ORDER BY LINE_ID ASC

When all errors have been corrected it is important to refresh the Materialized View Cache. The cache is vital for Materialized View related functionality in the IFS Business Reporting & Analysis services framework. There are two ways to do this:

Implementation Example

An implementation example related to a Data Mart version of a Dimension can be found here.