Prilagođavanje izvedbe upita za višedimenzijske baze podataka

Ako upotrebljavate višedimenzionalnu bazu podataka kao izvor podataka, u izvedbi servisa Oracle Analytics mogli biste doživjeti probleme koji će rezultirati generiranjem neoptimalnih upita višedimenzionalnih izraza (MDX).

Izmjenom dizajna možete unaprijediti MDX upite koje Oracle Analytics generira. To može imati značajan utjecaj, ne samo na izvedbu izvješća, već i na količinu resursa koji se upotrebljavaju u bazi podataka. Način na koji upotrebljavate podržane ili nepodržane funkcije u MDX-u značajno utječe na generirane MDX upite, a time i na izvedbu.

Budući da je svaki slučaj upotrebe jedinstven, vaš razvojni tim treba pregledati opcije, analizirati zapisnike upita za Oracle Analytics i odabrati najbolje rješenje za vaš slučaj upotrebe.

Ova tema ne otklanja probleme u izvedbi uzrokovane infrastrukturom, npr. mrežama, preglednicima ili prezentacijom izvješća.

Metodologija

Za poboljšanje izvedbe Oracle preporučuje izvršavanje sljedećih zadataka. Važno je da razumijete strukturu MDX upita, kao i zapisnike upita koje Oracle Analytics generira.

  • Pojednostavite generirane MDX upite.
  • Smanjite broj generiranih MDX upita.
  • Osigurajte primjenu optimalnih filtara i odabira u MDX upitu.
  • Uskladite izvedbu s administratorom za baze podataka (DBA) u višedimenzionalnoj bazi podataka i provjerite razloge za lošu razinu izvedbe izvorne baze podataka.
  • Izmjena analize temeljem povratnih informacija administratora za baze podataka.

Optimizacija koraka odabira

Nakon što optimizirate korake odabira, moći ćete pojednostaviti MDX upite, smanjiti broj generiranih MDX upita i povećati razinu izvedbe.

Sljedeća slika pokazuje primjer usporedbe optimiziranih i neoptimiziranih koraka odabira.

Slijedi opis za GUID-43E6F348-B14C-40DC-8C21-DA34DAE44344-default.jpg
.jpg

CASE naredbe

Funkcionalnost CASE naredbe nije podržana u MDX upitima i mora se uvijek primijeniti u servisu Oracle Analytics. Logika objašnjena u ovom odjeljku s obzirom na CASE naredbe valjana je za većinu funkcija koje nisu podržane u MDX upitima (vrijednost null itd.).

Postoje prednosti i nedostaci upotrebe CASE naredbi. Ako želite uključiti naredbe CASE u formule izvješća, neće biti uključene u MDX upit. To može pojednostaviti MDX upit i unaprijediti radne značajke. Međutim, time se onemogućava učinkovito filtriranje, što znači kako bi upit mogao vratiti više zapisa no što je potrebno.

Donosimo ograničenja kod upotrebe funkcije CASE naredbe:

  • Ako CASE naredba ne kombinira više članova, osnovni stupac koji se upotrebljava u naredbi treba se uključiti u upit i prikaze kao skriven zasebni stupac.
  • Ako CASE naredba kombinira više članova, osnovni stupac ne može biti uključen u prikaz bez da to utječe na razinu sabiranja. Ako je to slučaj:
    • Ako pravilo sabiranja mjere nije Vanjsko sabiranje, osnovni stupac mora se izostaviti iz upita.
    • Ako je pravilo sabiranja mjere Vanjsko sabiranje, osnovni stupac mora biti uključen u upit i isključen iz prikaza. Morate promijeniti pravilo sabiranja mjere sa zadanog na jednostavno interno pravilo sabiranja (SUM, MAX, MIN). To će funkcionirati samo ako interno pravilo sabiranja služi za kombiniranje članova i prikazuje točne rezultate.

Funkcija FILTER

Za razliku od naredbe CASE, funkcija FILTER može se isporučiti u bazu podataka radi izvođenja.

Glavna prednost upotrebe funkcije FILTER u formulama izvješća odnosi se na primjenu odabira na upit MDX uz smanjenje količine izračunatih i dohvaćenih podataka iz baze podataka.

Glavni nedostatak upotrebe funkcije FILTER u potencijalnom je povećanju broja izvršenih MDX upita. Po zadanim postavkama, izvodi se jedan upit za svaku upotrijebljenu funkciju FILTER.

Primjer za CASE u odnosu na FILTER

U ovom primjeru, korisnik traži izvješće koje pokazuje dobit po tromjesečju i SJ odabranog proizvoda. Osim toga, skladišne jedinice grupiraju se u 12 kategorija. Kategoriji Druga Cola dodijeljeni su sljedeći proizvodi: Cola, Dijetalna Cola i Zajednička dijetalna Cola.

Slijedi opis za GUID-7198F143-54E6-4A48-9579-96624936A94D-default.jpg
.jpg

Ovo je logički upit naredbe 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

Nema grupiranja temeljem naredbe CASE. Generirat će se jednostavan MDX upit, s naredbom CASE koju obrađuje 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]

Naredba CASE izvodi se na BI poslužitelju, što je prikazano kroz postavljanje postavke baze podataka na 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]

S druge strane, možete upotrijebiti filtriranje metrike dobiti kako biste dohvatili samo željene članove skupa. U tom ćete scenariju stvoriti tri metričke vrijednosti s primijenjenim odgovarajućim filtrima.

Ovo je logički upit naredbe 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

U tom će se scenariju generirati tri upita, po jedan za svaki filtar, a vi ćete osjetiti probleme u izvedbi.

1. upit:

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. upit:

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. upit:

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]

Primjer s primijenjenim filtrom proizvoda

Bolji je pristup uključiti stupac proizvoda u izvješće s jednim stupcem mjere, bez filtra. Zatim stvorite filtar koji uključuje tražene proizvode. Ako proizvode želite grupirati u različite kategorije, upotrijebite naredbu CASE. U tom će se scenariju generirati jedan MDX upit s filtriranim stupcima, a unatoč primjeni naredbe CASE, Oracle Analytics će upotrijebiti podskup podataka, ne sve zapise.

Donosimo i drugi scenarij u kojemu naredbe CASE uzrokuju probleme u izvedbi.

Razvojni programer primijenit će naredbu CASE radi promjene naziva robnih marki, a odzivnik dashboarda omogućit će korisnicima odabir robne marke.

Slijedi opis za GUID-56356AA9-2AF6-4A67-8ADD-FC4F7F70306C-default.jpg
.jpg

Slijedi opis za GUID-E63719C8-9936-412B-8228-F20E8F048C46-default.jpg
.jpg

Budući da MDX ne podržava naredbu CASE, u MDX upitu neće se moći primijeniti filtar za Robnu marku 2. Odabrat će se sve robne marke odabrane, a to nije optimalno.

Slijedi opis za GUID-6BE1F274-8257-4E31-8D42-406357A07B2A-default.jpg
.jpg

U takvom scenariju, Oracle preporučuje uklanjanje naredbe CASE i preimenovanje članova u bazi podataka ili stvaranje drugih naziva.