Justere ytelsen for flerdimensjonale databasespørringer

Når du bruker en flerdimensjonal database som datakilde i Oracle Analytics, kan du oppleve problemer med ytelsen som fører til at det genereres spørringer med flerdimensjonale uttrykk (MDX) som ikke er optimale.

Hvis du endrer utformingen, kan du forbedre MDX-spørringene som genereres i Oracle Analytics. Dette kan ha stor innvirkning både på rapportytelsen og ressursvolumet som brukes i databasen. Hvordan du bruker funksjoner som støttes eller ikke støttes, har stor innvirkning på de genererte MDX-spørringene, og dermed også på ytelsen.

Alle brukstilfeller er unike. Utviklingsteamet må derfor vurdere mulighetene, analysere spørringsloggene i Oracle Analytics og velge den beste løsningen for det aktuelle brukstilfellet.

Dette emnet dekker ikke svekket ytelse som skyldes problemer med infrastrukturen, for eksempel nettverk, nettlesere eller rapportpresentasjoner.

Metodikk

Oracle anbefaler at du utfører oppgavene nedenfor for å øke ytelsen. Det er viktig at du forstår MDX-spørringsstrukturen og spørringsloggene som genereres i Oracle Analytics.

  • Forenkle MDX-spørringene som genereres.
  • Reduser antallet genererte MDX-spørringer.
  • Sørg for at optimale filtre og valg brukes i MDX-spørringen.
  • Juster ytelsen med databaseadministratoren i den flerdimensjonale databasen, og finn ut hvorfor kildedatabasen fortsatt har dårlig ytelse.
  • Endre analysen basert på tilbakemelding fra databaseadministratoren.

Optimalisering av utvalgstrinn

Når du optimaliserer utvalgstrinn, kan du forenkle MDX-spørringene, redusere antallet genererte MDX-spørringer og øke ytelsen.

Figuren nedenforviser et eksempel på en sammenligning av optimaliserte og ikke-optimaliserte valgtrinn.

Beskrivelse av GUID-43E6F348-B14C-40DC-8C21-DA34DAE44344-default.jpg følger
.jpg

CASE-setninger

Funksjoner med CASE-setninger støttes ikke i MDX-spørringer og må alltid brukes i Oracle Analytics. Logikken som er forklart i dette avsnittet for CASE-setninger, gjelder for de fleste funksjoner som ikke støttes i MDX-spørringer (if null og så videre).

Det finnes både fordeler og ulemper med å bruke CASE-setninger. Når du inkluderer CASE-setninger i rapportformler, inkluderes de ikke i MDX-spørringen. Dette kan forenkle MDX-spørringen og gi bedre ytelse. Ulempen er imidlertid at du ikke kan filtrere like effektivt, slik at spørringen kanskje returnerer flere poster enn nødvendig.

Dette er begrensningene for bruk av funksjoner med CASE-setninger:

  • Hvis CASE-setningen ikke kombinerer flere medlemmer, må basiskolonnen som brukes i setningen, være inkludert i spørringen og visningene som en skjult separat kolonne.
  • Hvis CASE-setningen kombinerer flere medlemmer, kan ikke basiskolonnen være inkludert i visningene uten at det har innvirkning på aggregeringsnivået. Hvis dette er tilfellet:
    • Hvis aggregeringsregelen for måling ikke er Ekstern aggregering, må basiskolonnen utelates fra spørringen.
    • Hvis aggregeringsregelen for måling er Ekstern aggregering, må basiskolonnen være med i spørringen og utelatt fra visningen. Du må endre aggregeringsregelen for måling fra standardverdien til en enkel aggregeringsregel (SUM, MAX, MIN). Dette fungerer bare hvis den interne aggregeringsregelen brukes til å kombinere medlemmer og gir riktige resultater.

Funksjonen FILTER

I motsetning til funksjoner med CASE-setninger kan funksjonen FILTER sendes til databasen for utførelse.

Den største fordelen med å bruke funksjonen FILTER i rapportformler er at utvalget brukes i MDX-spørringen, og datavolumet som beregnes og hentes fra databasen, reduseres.

Den største ulempen med å bruke funksjonen FILTER er at det kan øke antallet MDX-spørringer som skal utføres. Det utføres som standard én spørring for hver FILTER-funksjon som brukes.

Eksempel på CASE kontra FILTER

I dette eksemplet ber brukeren om en rapport som viser lønnsomheten etter kvartal og valgt lagerenhet for produkt. I tillegg grupperes lagerenhetene i tolv kategorier. Kategorien Other Cola har følgende tilordnede LOB-produkter: Cola, Diet Cola og Shared Diet Cola.

Beskrivelse av GUID-7198F143-54E6-4A48-9579-96624936A94D-default.jpg følger
.jpg

Her er den logiske spørringen med CASE-setning:

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

Det finnes ingen gruppering basert på CASE-setningen. Det genereres en enkel MDX-spørring med CASE-setningen som behandles av 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]

CASE-setningen utføres på BI-tjeneren, og dette skjer fordi databaseinnstillingen er satt til 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]

Du kan også bruke et filter mot lønnsomhetsmålingen for å hente bare de nødvendige LOB-medlemmene. I dette scenarioet oppretter du tre målinger med bruk av de tilsvarende filtrene.

Her er den logiske spørringen med FILTER-setning:

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

I dette scenarioet genereres det tre spørringer, én for hvert filter, og du opplever problemer med ytelsen.

Spørring 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]

]]

Spørring 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]

]]

Spørring 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]

Eksempel på bruk av produktfilter

En bedre tilnærmingsmåte er å inkludere produktkolonnen i rapporten med én målingskolonne uten filter. Deretter oppretter du et filter som inkluderer de nødvendige produktene. Hvis du vil gruppere produktene i andre kategorier, kan du bruke en CASE-setning. I dette scenarioet genereres det én MDX-spørring med de filtrerte radene, og selv om CASE-setningen benyttes i Oracle Analytics, brukes delsettet med data i stedet for alle postene.

Her er et annet scenario der CASE-setninger fører til problemer med ytelsen.

En utvikler bruker en CASE-setning til å gi nytt navn til varemerker, og brukerne kan benytte en ledetekst for instrumentpanel til å velge varemerket.

Beskrivelse av GUID-56356AA9-2AF6-4A67-8ADD-FC4F7F70306C-default.jpg følger
.jpg

Beskrivelse av GUID-E63719C8-9936-412B-8228-F20E8F048C46-default.jpg følger
.jpg

Ettersom CASE-setningen ikke støttes i MDX, kan ikke filtreringen etter Brand2 brukes i MDX-spørringen. Alle varemerker er valgt, og dette optimaliseres ikke.

Beskrivelse av GUID-6BE1F274-8257-4E31-8D42-406357A07B2A-default.jpg følger
.jpg

I denne typen scenario anbefaler Oracle at du fjerner CASE-setningen og gir nytt navn til medlemmer i databasen eller oppretter aliaser.