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.
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.
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:
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.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:
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.
Í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 ONLYNincs 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 ONLYEbben 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.
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.
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.