OLAP rendszer Java-ban

Posted by | · · · · | Szoftverfejlesztés | Nincs hozzászólás a(z) OLAP rendszer Java-ban bejegyzéshez

Mi az OLAP?

Az OLAP betűszó jelentése On-Line Analitical Processing.
Java programozóként nem mindennap találkozunk OLAP rendszerekkel. Ha az ember Java EE alkalmazást fejleszt, akkor sokkal nagyobb a valószínűsége, hogy éppen egy OLTP (On-Line Transaction Processing) rendszert épít. Ne keseredjünk el, ha a két említett betűszó egyikével sem vagyunk tökéletesen tisztában! Az OLAP/OLTP rendszereknek komoly irodalma van, itt most csak dióhéjban összefoglalom a jellemzőiket.

OLAP vs OLTP

OLTP OLAP
Cél Üzleti logika és folyamatok Döntéstámogatás, vezetői információk, statisztika
Rendszer Operational System Adattárház (Data Warehouse)
Műveletek CRUD (INSERT,UPDATE,DELETE) műveletek Lekérdezések
Modell Üzleti entitások relációs adatbázisban Multidimenziós adatkockák (csillag séma)
Normalizáltság Normalizált (általában 3NF relációs adatbázis) Denormalizált adatszerkezet, redundáns adattárolás
Adatok Gyorsan változó adatok (adatintegritás fontos) Aggregált és historikus adatok többszintű felbontásban (pl. év – negyedév – hónap)
Teljesitmény Sok rövid tranzakció (tr per time unit) Komplex lekérdezések hosszú ideig futhatnak, feltöltés ritkán, ütemezett háttérfolyamatokkal

olap4j, Mondrian

Egyik projektünkben merült fel, hogy statisztikai lekérdezésekhez OLAP rendszert használnánk fel. Mivel Java-s projektről volt szó, ezért elsősorban Java alapú OLAP megoldásokat kerestünk. Így bukkantunk rá az olap4j-re, amely egy Java API az OLAP-hoz. Az API – nem véletlenül – nagyon hasonlít a JDBC-re és arra is épül, így viszonylag könnyen és gyorsan sikerült az első működő kódot összerakni benne. Egy lekérdezés futtatásához például ugyanúgy kell egy connection, aztán abból egy statement, amit végrehajtva megkapjuk a lekérdezés eredményét valamilyen resultset-be csomagolva.

olap4j vs JDBC

JDBC olap4j
java.sql.Connection org.olap4j.OlapConnection
java.sql.Statement org.olap4j.OlapStatement
java.sql.ResultSet org.olap4j.CellSet

Az olap4j-től jutottunk el a Mondrian-hoz, ami egy OLAP engine és egyben az olap4j referencia implementációja. A Mondrian egy ROLAP (Relational OLAP) rendszer. Ez azt jelenti, hogy a multidimenziós adatmodellt relációs adatbázisban valósítják meg. A ROLAP-nál a legegyszerűbb esetben egy adatkocka (csillagséma) úgy jön létre, hogy a ténytábla több dimenzió táblára hivatkozik. Bonyolultabb esetben a ténytábla is és a dimenziók is több táblára lehetnek szétbontva (hópehely séma). Meg kell említeni, hogy a Mondrian feladata itt a multidimenziós adatmodell kezelése és a lekérdezések értelmezése, futtatása, de nem feladata a modellnek megfelelő adatszerkezet (tény táblák és dimenzió táblák) adatokkal való feltöltése. A multidimenziós adatkockák feltöltését valamilyen forrás rendszerekből ETL (Extract, Transform, Load) eljárásnak nevezik. Ezt tehát a Mondrian-tól teljesen függetlenül Talend-del csináltuk. Az ETL eljárás mindig teljesen egyedi, függ a forrás rendszerek szerkezetétől, elérésétől és persze a felépíteni kívánt multidimenziós adatmodelltől, ezért itt erről nem is írok többet.

MDX lekérdező nyelv

Az MDX (MultiDimensional eXpression) lekérdező nyelvet OLAP rendszerekhez fejlesztették ki. A nyelv erősen emlékeztet az SQL-re, de míg az a relációs adattáblákkal dolgozik, addig az MDX a multidimenziós adatmodell elemeivel: kocka, dimenzió, tényadat. Az SQL-hez hasonlóan az MDX-nek is vannak nyelvjárásai, a Mondrian MDX nyelvjárásáról itt található a dokumentáció.

Multidimenziós séma xml

A multidimenziós adatmodellt a Mondrian egy séma xml-ben tárolja. Ebben definiálhatjuk az adatkockákat (Cube), a dimenziókat (Dimension) és a modellnek megfelelő relációs adatbázis struktúrát. Egy OlapConnection létrehozásakor a connection string-ben az adatbázis elérhetőségén kívűl meg kell adni a séma xml helyét is. Ez alapján építi fel a Mondrian a memóriában a multidimenziós adatmodellt. A Mondrian dokumentációjában több helyen hivatkoznak a FoodMart példa adatmodellre. Ez egy élelmiszer áruházlánc működéséhez felépített fiktív multidimenziós adatmodell. Például a Sales kocka tárolja az áruházlánc forgalmi adatait többféle dimenzió szerinti bontásban (termék, idő, áruház, vásárlók neme, végzettsége, stb.)

Dimenzió definiálása a modellben

A séma xml-ben a Dimension elemmel definiálhatunk dimenziót. Az alábbi példában a FoodMart modell áruház (Store) dimenziója látható. A dimenziók hierarchikus felépítésűek. Az áruház dimenziónak például ország/állam/város/konkrét áruház szintjei vannak.

    <Dimension name="Store">
        <Hierarchy hasAll="true" primaryKey="store_id">
            <Table name="store"/>
            <Level name="Store Country" column="store_country" uniqueMembers="true"/>
            <Level name="Store State" column="store_state" uniqueMembers="true"/>
            <Level name="Store City" column="store_city" uniqueMembers="false"/>
            <Level name="Store Name" column="store_name" uniqueMembers="true"/>
        </Hierarchy>
    </Dimension>

Adatkocka definiálása

A FoodMart példában a Sales kocka használja a Store dimenziót. A séma xml-ben a DimensionUsage elemmel hivatkozhatunk globálisan létrehozott dimenzióra. Létrehozhatunk lokális (csak az adatkockában látható) dimenziót is a Dimension elemmel. Ehhez a Dimension-t az adott Cube elemen belül kell elhelyezni.

<Cube name="Sales" defaultMeasure="Unit Sales">
   <!-- ténytábla -->
   <Table name="sales_fact"/>

   <!-- globálisan definiált Store dimenzió használata  -->
   <DimensionUsage name="Store" source="Store" foreignKey="store_id"/>

   <!-- egyéb dimenzió hivatkozások és kocka szintű dimenzió definíciók -->

   <!-- legalább egy tényadat a dimenziók által kifeszített térben -->
   <Measure name="Unit Sales" column="unit_sales" aggregator="sum"
           formatString="Standard"/>
</Cube>   

OlapConnection és OLAP Schema használata

Az alábbi kódrészletben látszik a JDBC alapú connection kezelés és az adatmodell séma elkérése. A Schema objektum a connectionString-ben megadott séma xml alapján épül fel.

import java.sql.Connection;
import java.sql.DriverManager;
import org.olap4j.OlapConnection;
import org.olap4j.OlapWrapper;
import org.olap4j.metadata.Schema;

Connection connection = DriverManager.getConnection(connectionString);
OlapWrapper wrapper = (OlapWrapper) connection;
OlapConnection olapConnection = wrapper.unwrap(OlapConnection.class);
Schema schema = olapConnection.getOlapSchema();

Adatkockák, Dimenziók bejárása

A Schema objektumon keresztül bejárhatjuk a multidimenziós modell elemeit: az adatkockákat, dimenziókat, stb.

import org.olap4j.metadata.Cube;
import org.olap4j.metadata.Dimension;
import org.olap4j.metadata.Hierarchy;
import org.olap4j.metadata.Level;
import org.olap4j.metadata.Schema;

Cube cube = schema.getCubes().get("Sales");
Dimension dimension = cube.getDimensions().get("Store");
Hierarchy hierarchy = dimension.getDefaultHierarchy();
Level level = hierarchy.getLevels().get("Store City");

MDX lekérdezés futtatása

Az MDX lekérdezést összerakhatjuk szövegesen vagy a modell elemeit felhasználva dinamikusan és typesafe módon. (Utóbbihoz lásd a ParseTreeNode interfészt és társait az org.olap4j.mdx package-ben)

import org.olap4j.CellSet;
import org.olap4j.OlapConnection;
import org.olap4j.OlapException;
import org.olap4j.OlapStatement;

String mdx = "SELECT {[Time].[Quarter]} ON COLUMNS,"
                + "  {[Product].[Product Family]} ON ROWS"
                + " FROM [Sales]";
OlapStatement statement = olapConnection.createStatement();
CellSet cellSet = statement.executeOlapQuery(mdx);

A lekérdezés eredményét tehát egy CellSet interfészen kapjuk meg. A CellSet-et bejárva (Axis-ok mentén, Cell-ekből kiszedve az információt) elérhetőek a lekérdezett adatok.

SAIKU

A fejlesztés során bukkantunk rá a SAIKU-ra, ami egy Mondrian alapú OLAP alkalmazás. A SAIKU nagyon hasznos volt számunkra az OLAP és a Mondrian megismeréséhez. Webes felületén összekattintgathatjuk a lekérdezést, sőt az MDX query-t is megmutatja, ami nagy segítség az MDX nyelv megismeréséhez. A SAIKU-hoz Online demo is elérhető. SAIKU webes felülete:

SAIKU Demo

Források

OLTP vs OLAP
Adattárházak
OLAP vs OLTP: What makes the difference?
olap4j
Mondrian
FoodMart séma
SAIKU
SAIKU Online Demo


No Comments

Leave a comment