A multidimenzionális adatbázis lekérdezési teljesítményének fokozása

Ha multidimenzionális adatbázist használ adatforrásként, teljesítménybeli problémákat tapasztalhat, amelyek azt eredményezhetik, hogy szuboptimális multidimenzionális adatbázis (MDX) lekérdezések jönnek létre.

A terv módosításával javíthatja az Oracle Analytics által generált MDX-lekérdezések teljesítményét. Ennek óriási hatása lehet, nemcsak a kimutatás teljesítményére, hanem az adatbázisban felhasznált erőforrások mértékére is. A támogatott és nem támogatott függvények használata nagy hatással van a létrehozott MDX-lekérdezésekre, és ezzel a teljesítményre is.

Minden használati eset egyedi, ezért a fejlesztőcsapat feladata, hogy áttekintse a lehetőségeket, elemezze az Oracle Analytics lekérdezési naplókat, és kiválassza az Ön használati esetének legjobb megoldást.

Ez a témakör nem foglalkozik az Ön infrastruktúrája (például hálózatok, böngészők vagy kimutatásbemutatók) által okozott teljesítményproblémákkal.

Metodika

Az Oracle azt javasolja, hogy hajtsa végre a következő feladatokat a teljesítmény növelése érdekében. Fontos megérteni az MDX-lekérdezés struktúráját, valamint az Oracle Analytics által létrehozott lekérdezési naplókat is.

  • Egyszerűsítse le a generált MDX-lekérdezéseket.
  • Csökkentse a generált MDX-lekérdezések számát.
  • Győződjön meg arról, hogy az MDX-lekérdezésben optimális szűrőket és kijelöléseket alkalmaznak.
  • Végezze el a teljesítmény finomhangolását az adatbázis-adminisztrátorral (DBA) a multidimenzionális adatbázison, és ellenőrizze, hogy a forrásadatbázis teljesítménye miért nem kielégítő még mindig.
  • Módosítsa az elemzést az adatbázis adminisztrátorának visszajelzései alapján.

Kijelölési lépések optimalizálása

A kiválasztási lépések optimalizálásával leegyszerűsítheti az MDX-lekérdezéseket, csökkentheti a generált MDX-lekérdezések számát, és növelheti a teljesítményt.

A következő ábrán egy példa látható, amely összehasonlítja az optimalizált és a nem optimalizált kiválasztási lépéseket.

A(z) GUID-43E6F348-B14C-40DC-8C21-DA34DAE44344-default.jpg leírása
.jpg ábra leírása

CASE utasítások

A CASE utasítás funkcióit az MDX-lekérdezések nem támogatják, és mindig az Oracle Analytics szolgáltatásban kell őket alkalmazni. A CASE utasításokkal kapcsolatban ebben a szakaszban ismertetett logika a legtöbb olyan függvényre érvényes, amelyet az MDX-lekérdezések nem támogatnak (if null stb.).

A CASE utasítások használatának előnyei és hátrányai is vannak. Ha CASE utasításokat ír a kimutatásképletekbe, ezek nem kerülnek be az MDX-be. Ez egyszerűsítheti az MDX-lekérdezést, és javíthatja a teljesítményt. Ennek azonban negatívuma is van, mégpedig az, hogy nem olyan hatékony a szűrés – ez azt jelenti, hogy a lekérdezés a szükségesnél több rekordot adhat vissza.

A CASE utasítás használatára a következő korlátozások vonatkoznak:

  • Ha a CASE utasítás nem kombinál össze több tagot, akkor az utasításban használt alaposzlopnak külön rejtett oszlopként kell szerepelnie a lekérdezésben és a nézetekben.
  • Ha a CASE utasítás több tagot kombinál össze, az alaposzlop nem szerepelhet a nézetben anélkül, hogy hatással lenne az összesítés szintjére. Ilyen esetben:
    • Ha a mérőszám összesítési szabálya nem Külső összesítés, akkor az alaposzlopot ki kell zárni a lekérdezésből.
    • Ha a mérőszám összesítési szabálya Külső összesítés, akkor az alaposzlopnak szerepelnie kell a lekérdezésben, és ki kell zárni a nézetből. A mérőszám összesítési szabályát az alapértelmezettről egy egyszerű belső összesítési szabályra kell módosítani (SUM, MAX, MIN). Ez csak akkor működik, ha a belső összesítési szabályt a tagok kombinálására használják, és megfelelő eredményeket ad.

FILTER függvény

A CASE utasítással ellentétben a FILTER függvény elküldhető végrehajtásra az adatbázisba.

A kimutatásképletekben a FILTER függvény használatának fő előnye, hogy a kijelölés alkalmazásra kerül az MDX-lekérdezésben, és csökken az adatbázisból kiszámított és lekért adatok mennyisége.

A FILTER függvény használatának fő hátránya, hogy növelheti a végrehajtott MDX-lekérdezések számát. Alapértelmezés szerint minden használt FILTER függvényhez egyetlen lekérdezés kerül végrehajtásra.

A CASE és a FILTER összehasonlítása példával

Ebben a példában a felhasználó egy kimutatást kér, amely negyedévenként és a kiválasztott termék cikkszáma szerint mutatja a nyereséget. Ezenkívül a cikkszámok 12 kategóriába vannak csoportosítva. Az Other Cola kategóriához az LOB következő termékei vannak hozzárendelve: Cola, Diet Cola és Shared Diet Cola.

A(z) GUID-7198F143-54E6-4A48-9579-96624936A94D-default.jpg leírása
.jpg ábra leírása

Íme a CASE utasítás logikai lekérdezése:

SELECT

   0 s_0,

   CASE when XSA('Admin'.'Sample.BasicPM')."Product"."Product SKU" in ('Cola','Diet Cola','Shared Diet Cola') THEN 'Other Cola' ELSE XSA('Admin'.'Sample.BasicPM')."Product"."Product SKU" END s_1,

   DESCRIPTOR_IDOF(XSA('Admin'.'Sample.BasicPM')."Product"."Category") s_2,

   DESCRIPTOR_IDOF(XSA('Admin'.'Sample.BasicPM')."Product"."Product SKU") s_3,

   DESCRIPTOR_IDOF(XSA('Admin'.'Sample.BasicPM')."Year"."Quarter") s_4,

   SORTKEY(XSA('Admin'.'Sample.BasicPM')."Product"."Category") s_5,

   SORTKEY(XSA('Admin'.'Sample.BasicPM')."Product"."Product SKU") s_6,

   SORTKEY(XSA('Admin'.'Sample.BasicPM')."Year"."Quarter") s_7,

   XSA('Admin'.'Sample.BasicPM')."Product"."Category" s_8,

   XSA('Admin'.'Sample.BasicPM')."Product"."Product SKU" s_9,

   XSA('Admin'.'Sample.BasicPM')."Year"."Quarter" s_10,

   XSA('Admin'.'Sample.BasicPM')."Basic"."Profit" s_11

FROM XSA('Admin'.'Sample.BasicPM')

ORDER BY 8 ASC NULLS LAST, 11 ASC NULLS LAST, 5 ASC NULLS LAST, 2 ASC NULLS LAST, 7 ASC NULLS LAST, 10 ASC NULLS LAST, 4 ASC NULLS LAST, 6 ASC NULLS LAST, 9 ASC NULLS LAST, 3 ASC NULLS LAST

FETCH FIRST 125001 ROWS ONLY

Nincs olyan csoportosítás, amely a CASE utasításon alapul. Egy egyszerű MDX-lekérdezés jön létre, a CASE utasítást az Oracle Analytics dolgozza fel:

With 
  set [_Product3]  as 'Descendants([Product], [Product].Generations(3), leaves)'
  set [_Year2]  as 'Descendants([Year], [Year].Generations(2), leaves)'
select 
  { [Measures].[Profit]
  } on columns,
  NON EMPTY {crossjoin({[_Year2]},{[_Product3]})} properties GEN_NUMBER, [Product].[MEMBER_UNIQUE_NAME], [Product].[Memnor], [Year].[MEMBER_UNIQUE_NAME], [Year].[Memnor] on rows 
from [Sample.Basic]

A CASE utasítás végrehajtásra kerül a BI Serveren, és ez az alapján látható, hogy az adatbázis beállítása database 0:0,0 lesz:

 RqList <<11777451>> [for database 0:0,0]
                            D1.c6 as c6 [for database 0:0,0],
                            D1.c4 as c4 [for database 0:0,0],
                            case  when D1.c7 in ([ 'Cola', 'Diet Cola', 'Shared Diet Cola'] ) then 'Other Cola' else D1.c7 end  as c2 [for database 0:0,0],
                            D1.c5 as c5 [for database 0:0,0],
                            D1.c3 as c3 [for database 0:0,0],
                            D1.c1 as c1 [for database 0:0,0],
                            D1.c7 as c7 [for database 0:0,0],
                            D1.c8 as c8 [for database 0:0,0]

Alternatív megoldásként használhat szűrőt a profit mérőszámaira, hogy csak a szükséges LOB-tagokat kérje le. Ebben a forgatókönyvben három mérőszámot hoz létre a megfelelő szűrőkkel.

Íme a FILTER utasítás logikai lekérdezése:

SELECT

   0 s_0,

   DESCRIPTOR_IDOF(XSA('Admin'.'Sample.BasicPM')."Product"."Category") s_1,

   DESCRIPTOR_IDOF(XSA('Admin'.'Sample.BasicPM')."Product"."Product SKU") s_2,

   DESCRIPTOR_IDOF(XSA('Admin'.'Sample.BasicPM')."Year"."Quarter") s_3,

   SORTKEY(XSA('Admin'.'Sample.BasicPM')."Product"."Category") s_4,

   SORTKEY(XSA('Admin'.'Sample.BasicPM')."Product"."Product SKU") s_5,

   SORTKEY(XSA('Admin'.'Sample.BasicPM')."Year"."Quarter") s_6,

   XSA('Admin'.'Sample.BasicPM')."Product"."Category" s_7,

   XSA('Admin'.'Sample.BasicPM')."Product"."Product SKU" s_8,

   XSA('Admin'.'Sample.BasicPM')."Year"."Quarter" s_9,

   FILTER(XSA('Admin'.'Sample.BasicPM')."Basic"."Profit" USING XSA('Admin'.'Sample.BasicPM')."Product"."Product SKU" in ('Cola','Diet Cola','Shared Diet Cola')) s_10,

   FILTER(XSA('Admin'.'Sample.BasicPM')."Basic"."Profit" USING XSA('Admin'.'Sample.BasicPM')."Product"."Product SKU" in ('Sasprilla','Birch Beer','Dark Cream')) s_11,

   FILTER(XSA('Admin'.'Sample.BasicPM')."Basic"."Profit" USING XSA('Admin'.'Sample.BasicPM')."Product"."Product SKU" in ('xxxxx')) s_12

FROM XSA('Admin'.'Sample.BasicPM')

ORDER BY 7 ASC NULLS LAST, 10 ASC NULLS LAST, 4 ASC NULLS LAST, 6 ASC NULLS LAST, 9 ASC NULLS LAST, 3 ASC NULLS LAST, 5 ASC NULLS LAST, 8 ASC NULLS LAST, 2 ASC NULLS LAST

FETCH FIRST 125001 ROWS ONLY

Ebben a forgatókönyvben három lekérdezés jön létre (minden szűrőhöz egy), és teljesítménybeli problémák lépnek fel.

1. lekérdezés:

With

  set [_Product3]  as 'Filter([Product].Generations(3).members, ((IIF(IsValid([Product].CurrentMember.MEMBER_ALIAS), [Product].CurrentMember.MEMBER_ALIAS, [Product].CurrentMember.MEMBER_Name) = "xxxxx")))'

  set [_Year2]  as 'Descendants([Year], [Year].Generations(2), leaves)'

select

  { [Measures].[Profit]

  } on columns,

  NON EMPTY {crossjoin({[_Year2]},{[_Product3]})} properties MEMBER_NAME, GEN_NUMBER, property_expr([Product], [MEMBER_NAME], Ancestor(currentaxismember(), [Product].Generations(2)), "Category_Null_Alias_Replacement"), property_expr([Product], [Default], Ancestor(currentaxismember(), [Product].Generations(2)), "Category"), property_expr([Product], [MEMBER_UNIQUE_NAME], Ancestor(currentaxismember(), [Product].Generations(2)), "Category - Member Key"), property_expr([Product], [Memnor], Ancestor(currentaxismember(), [Product].Generations(2)), "Category - Memnor"), [Product].[MEMBER_UNIQUE_NAME], [Product].[Memnor], [Year].[MEMBER_UNIQUE_NAME], [Year].[Memnor] on rows

from [Sample.Basic]

]]

2. lekérdezés:

With

  set [_Product3]  as 'Filter([Product].Generations(3).members, ((IIF(IsValid([Product].CurrentMember.MEMBER_ALIAS), [Product].CurrentMember.MEMBER_ALIAS, [Product].CurrentMember.MEMBER_Name) = "Birch Beer") OR (IIF(IsValid([Product].CurrentMember.MEMBER_ALIAS), [Product].CurrentMember.MEMBER_ALIAS, [Product].CurrentMember.MEMBER_Name) = "Dark Cream") OR (IIF(IsValid([Product].CurrentMember.MEMBER_ALIAS), [Product].CurrentMember.MEMBER_ALIAS, [Product].CurrentMember.MEMBER_Name) = "Sasprilla")))'

  set [_Year2]  as 'Descendants([Year], [Year].Generations(2), leaves)'

select

  { [Measures].[Profit]

  } on columns,

  NON EMPTY {crossjoin({[_Year2]},{[_Product3]})} properties MEMBER_NAME, GEN_NUMBER, property_expr([Product], [MEMBER_NAME], Ancestor(currentaxismember(), [Product].Generations(2)), "Category_Null_Alias_Replacement"), property_expr([Product], [Default], Ancestor(currentaxismember(), [Product].Generations(2)), "Category"), property_expr([Product], [MEMBER_UNIQUE_NAME], Ancestor(currentaxismember(), [Product].Generations(2)), "Category - Member Key"), property_expr([Product], [Memnor], Ancestor(currentaxismember(), [Product].Generations(2)), "Category - Memnor"), [Product].[MEMBER_UNIQUE_NAME], [Product].[Memnor], [Year].[MEMBER_UNIQUE_NAME], [Year].[Memnor] on rows

from [Sample.Basic]

]]

3. lekérdezés:

With

  set [_Product3]  as 'Filter([Product].Generations(3).members, ((IIF(IsValid([Product].CurrentMember.MEMBER_ALIAS), [Product].CurrentMember.MEMBER_ALIAS, [Product].CurrentMember.MEMBER_Name) = "Cola") OR (IIF(IsValid([Product].CurrentMember.MEMBER_ALIAS), [Product].CurrentMember.MEMBER_ALIAS, [Product].CurrentMember.MEMBER_Name) = "Diet Cola") OR (IIF(IsValid([Product].CurrentMember.MEMBER_ALIAS), [Product].CurrentMember.MEMBER_ALIAS, [Product].CurrentMember.MEMBER_Name) = "Shared Diet Cola")))'

  set [_Year2]  as 'Descendants([Year], [Year].Generations(2), leaves)'

select

  { [Measures].[Profit]

  } on columns,

  NON EMPTY {crossjoin({[_Year2]},{[_Product3]})} properties MEMBER_NAME, GEN_NUMBER, property_expr([Product], [MEMBER_NAME], Ancestor(currentaxismember(), [Product].Generations(2)), "Category_Null_Alias_Replacement"), property_expr([Product], [Default], Ancestor(currentaxismember(), [Product].Generations(2)), "Category"), property_expr([Product], [MEMBER_UNIQUE_NAME], Ancestor(currentaxismember(), [Product].Generations(2)), "Category - Member Key"), property_expr([Product], [Memnor], Ancestor(currentaxismember(), [Product].Generations(2)), "Category - Memnor"), [Product].[MEMBER_UNIQUE_NAME], [Product].[Memnor], [Year].[MEMBER_UNIQUE_NAME], [Year].[Memnor] on rows

from [Sample.Basic]

Alkalmazott termékszűrő példával

Jobb megközelítés, ha a termékoszlopot egyetlen mérőszámoszloppal, szűrő nélkül szerepelteti a kimutatásban. Ezután hozzon létre egy szűrőt, amely a szükséges termékeket tartalmazza. Ha a termékeket különböző kategóriákba szeretné csoportosítani, használja a CASE utasítást. Ebben a forgatókönyvben egyetlen MDX-lekérdezés jön létre a szűrt sorokkal, és bár az Oracle Analytics alkalmazza a CASE utasítást, az adatok csak egy részhalmazát használja, és nem az összes rekordot.

Íme egy másik forgatókönyv, ahol a CASE utasítások teljesítménybeli problémákat okoznak.

A fejlesztő a CASE utasítást alkalmazza a márkák átnevezéséhez, és az irányítópultprompt segítségével a felhasználók kiválaszthatják a márkát.

A(z) GUID-56356AA9-2AF6-4A67-8ADD-FC4F7F70306C-default.jpg leírása
.jpg ábra leírása

A(z) GUID-E63719C8-9936-412B-8228-F20E8F048C46-default.jpg leírása
.jpg ábra leírása

Mivel a CASE utasítás nem támogatott az MDX-ben, a Brand2 szűrője nem alkalmazható az MDX-lekérdezésben. Minden márka ki van választva, és ez nincs optimalizálva.

A(z) GUID-6BE1F274-8257-4E31-8D42-406357A07B2A-default.jpg leírása
.jpg ábra leírása

Ebben a forgatókönyvben az Oracle azt javasolja, hogy távolítsa el a CASE utasítást, és nevezze át a tagokat az adatbázisban, vagy hozzon létre alternatív neveket.