Ladenie výkonu dopytov na multidimenzionálnu databázu

Keď ako dátový zdroj v službe Oracle Analytics použijete multidimenzionálnu databázu, môžete zaznamenať problémy s výkonom, ktoré spôsobia nižšiu kvalitu generovaných dopytov MDX (multidimensional expression).

Úpravou návrhu môžete zlepšiť dopyty MDX, ktoré služba Oracle Analytics generuje. Môže to mať obrovský vplyv nielen na výkon zostáv, ale aj na množstvo prostriedkov využívaných v databáze. Spôsob, akým využívate podporované alebo nepodporované funkcie, výrazne vplýva na generované dopyty MDX, a teda na výkon.

Keďže každý prípad použitia je jedinečný, vývojársky tím by mal skontrolovať voľby, analyzovať protokoly dopytov služby Oracle Analytics a vybrať to najlepšie riešenie pre váš prípad použitia.

Táto téma sa nevenuje problémom s výkonom spôsobeným vašou infraštruktúrou, ako sú siete, prehľadávače alebo prezentácia zostavy.

Metodológia

Spoločnosť Oracle odporúča vykonať nasledujúce úlohy na zvýšenie výkonu. Je dôležité, aby ste chápali štruktúru dopytov MDX, ako aj protokoly dopytov, ktoré Oracle Analytics generuje.

  • Zjednodušte generované dopyty MDX.
  • Znížte počet generovaných dopytov MDX.
  • Zaistite, aby sa v dopyte MDX používali optimálne filtre a výbery.
  • Vylaďte výkon s administrátorom databázy v multidimenzionálnej databáze a preverte, prečo pretrváva nedostatočný výkon zdrojovej databázy.
  • Modifikujte analýzu na základe spätnej väzby administrátora databázy.

Optimalizácia krokov výberu

Keď optimalizujete kroky výberu, môžete zjednodušiť dopyty MDX, znížiť počet generovaných dopytov MDX a zvýšiť výkon.

Na nasledujúcom obrázku je znázornený príklad porovnania optimalizovaných a neoptimalizovaných krokov výberu.

Popis GUID-43E6F348-B14C-40DC-8C21-DA34DAE44344-default.jpg je uvedený nižšie
.jpg

Príkazy CASE

Funkcionalita príkazov CASE nie je v dopytoch MDX podporovaná a musí byť vždy použitá v službe Oracle Analytics. Logika vysvetlená v tejto sekcii v súvislosti s príkazmi CASE platí pre väčšinu funkcií, ktoré nie sú v dopytoch MDX podporované (if null atď.).

Používanie príkazov CASE má svoje výhody a nevýhody. Keď do vzorcov zostavy pridáte príkazy CASE, nebudú zahrnuté do dopytu MDX. Môže sa tým zjednodušiť dopyt MDX a zvýšiť výkon. Kompromisom je však to, že dáta nemožno filtrovať tak efektívne, čo znamená, že dopyt môže vrátiť viac záznamov, ako je potrebné.

Používanie funkcionality príkazov CASE má nasledujúce obmedzenia:

  • Ak príkaz CASE nekombinuje viaceré členy, základný stĺpec použitý v príkaze by mal byť zahrnutý do dopytu a do zobrazení ako skrytý samostatný stĺpec.
  • Ak príkaz CASE kombinuje viaceré členy, základný stĺpec nemožno zahrnúť do zobrazenia bez toho, aby to nemalo vplyv na úroveň agregácie. Ak je to tak:
    • Ak pravidlo agregácie miery nie je Externá agregácia, základný stĺpec musí byť z dopytu vylúčený.
    • Ak pravidlo agregácie miery je Externá agregácia, základný stĺpec musí byť zahrnutý do dopytu a vylúčený zo zobrazenia. Je potrebné zmeniť pravidlo agregácie miery z predvoleného na pravidlo jednoduchej internej agregácie (SUM, MAX, MIN). Funguje to len v prípade, že pravidlo internej agregácie sa používa na kombinovanie členov a poskytuje správne výsledky.

Funkcia FILTER

Na rozdiel od funkcionality príkazov CASE je funkciu FILTER možné odoslať do databázy na spustenie.

Hlavnou výhodou použitia funkcie FILTER vo vzorcoch zostáv je, že výber sa použije v dopyte MDX a zníži sa objem dát vypočítaných a vyvolaných z databázy.

Hlavnou nevýhodou funkcie FILTER je, že môže zvýšiť počet vykonaných dopytov MDX. Predvolene sa vykoná jeden dopyt pre každú použitú funkciu FILTER.

Príklad porovnávajúci príkaz CASE a príkaz FILTER

V tomto príklade používateľ požiada o zostavu, ktorá zobrazí zisk podľa štvrťroka a vybranej jednotky SKU produktu. Okrem toho sú jednotky SKU zoskupené do 12 kategórií. Kategória Other Cola má priradené nasledujúce produkty: Cola, Diet Cola a Shared Diet Cola.

Popis GUID-7198F143-54E6-4A48-9579-96624936A94D-default.jpg je uvedený nižšie
.jpg

Toto je logický dopyt príkazu CASE:

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

Na základe príkazu CASE sa nevykoná žiadne zoskupenie. Vygeneruje sa jednoduchý dopyt MDX s príkazom CASE, ktorý je spracovaný v službe Oracle Analytics:

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]

Príkaz CASE je spustený na serveri BI, čo vidieť podľa hodnoty nastavenia databázy database 0:0,0:

 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]

Ako alternatívu môžete použiť filter na metriku zisku a vyvolať len požadované členy predmetu obchodnej činnosti. V tomto scenári vytvoríte tri metriky so zodpovedajúcimi použitými filtrami.

Toto je logický dopyt príkazu FILTER:

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

V tomto scenári sa vygenerujú tri dopyty, jeden pre každý filter, a zaznamenáte problémy s výkonom.

Dopyt 1:

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]

]]

Dopyt 2:

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]

]]

Dopyt 3:

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]

Príklad použitia filtra produktov

Lepším riešením je zahrnúť stĺpec produktov do zostavy s jedným stĺpcom miery bez filtra. Potom vytvoríte filter, ktorý zahŕňa požadované produkty. Ak chcete zoskupiť produkty do rôznych kategórií, použite príkaz CASE. V tomto scenári sa vygeneruje jeden dopyt MDX s vyfiltrovanými riadkami, a aj keď Oracle Analytics použije príkaz CASE, použije len podmnožinu dát, nie všetky záznamy.

Tu je ďalší scenár, v ktorom príkazy CASE spôsobujú problémy s výkonom.

Vývojár použije príkaz CASE na premenovanie obchodných značiek a výzva panela umožní používateľom vybrať obchodnú značku.

Popis GUID-56356AA9-2AF6-4A67-8ADD-FC4F7F70306C-default.jpg je uvedený nižšie
.jpg

Popis GUID-E63719C8-9936-412B-8228-F20E8F048C46-default.jpg je uvedený nižšie
.jpg

Keďže príkaz CASE nie je v dopyte MDX podporovaný, filter Brand2 nemožno použiť v dopyte MDX. Vybrané sú všetky značky, čo nie je optimálne.

Popis GUID-6BE1F274-8257-4E31-8D42-406357A07B2A-default.jpg je uvedený nižšie
.jpg

V tomto type scenára spoločnosť Oracle odporúča odobrať príkaz CASE a premenovať členy v databáze alebo vytvoriť aliasy.