Lorsque vous utilisez une base de données multidimensionnelle comme source de données dans Oracle Analytics, vous pouvez rencontrer des problèmes de performance qui se traduisent par la génération d'interrogations d'expression multidimensionnelle (MDX) sous-optimales.
En modifiant la conception, vous pouvez améliorer les interrogations MDX générées par Oracle Analytics. Cela peut avoir une incidence considérable, non seulement sur la performance de votre rapport, mais aussi sur le volume des ressources utilisées dans la base de données. La manière dont vous utilisez les fonctions prises en charge ou non prises en charge a une incidence considérable sur les interrogations MDX générées et sur la performance.
Étant donné que chaque cas d'utilisation est unique, il appartient à votre équipe de développement de passer en revue les options, d'analyser les journaux d'interrogations d'Oracle Analytics et de sélectionner la meilleure solution pour votre cas d'utilisation.
Cette rubrique n'aborde pas les problèmes de performance causés par votre infrastructure, tels que réseaux, navigateurs ou présentation de rapport.
Méthodologie
Pour améliorer la performance, Oracle vous recommande d'effectuer les tâches suivantes. Il est important de comprendre la structure des interrogations MDX ainsi que les journaux d'interrogations générés par Oracle Analytics.
Optimisation des étapes de sélection
L'optimisation des étapes de sélection permet de simplifier les interrogations MDX, de réduire le nombre d'interrogations MDX générées et d'améliorer la performance.
L'illustration suivante présente un exemple de comparaison des étapes de sélection optimisées et des étapes de sélection non optimisées.
.jpg
Énoncés CASE
La fonctionnalité d'énoncé CASE
n'est pas prise en charge dans les interrogations MDX et doit toujours être appliquée dans Oracle Analytics. La logique expliquée dans cette section concernant les énoncés CASE
est valable pour la plupart des fonctions qui ne sont pas prises en charge dans les interrogations MDX (if null
, etc.).
L'utilisation des énoncés CASE
présente des avantages et des inconvénients. Lorsque vous ajoutez des énoncés CASE
dans des formules de rapport, ils ne figurent pas dans l'interrogation MDX. Cela peut simplifier l'interrogation MDX et améliorer la performance. Toutefois, la contrepartie est que le filtrage n'étant pas aussi efficace, l'interrogation peut retourner plus d'enregistrements que nécessaire.
Les restrictions liées à l'utilisation de la fonctionnalité d'énoncé CASE
sont les suivantes :
CASE
ne combine pas plusieurs membres, la colonne de base utilisée dans l'énoncé doit être incluse dans l'interrogation et les vues en tant que colonne distincte masquée.CASE
combine plusieurs membres, la colonne de base ne peut pas être incluse dans la vue sans avoir une incidence sur le niveau d'agrégation. Si le cas se présente :
SUM
, MAX
, MIN
). Cela ne fonctionne que si la règle d'agrégation interne est utilisée pour combiner les membres et fournit des résultats corrects.Fonction FILTER
Contrairement à l'énoncé CASE
, la fonction FILTER
peut être envoyée à la base de données pour exécution.
Le principal avantage de l'utilisation de la fonction FILTER
dans les formules de rapport est que la sélection est appliquée dans l'interrogation MDX et que le volume de données calculées et extraites de la base de données est réduit.
Le principal inconvénient de l'utilisation de la fonction FILTER
est qu'elle peut augmenter le nombre d'interrogations MDX exécutées. Par défaut, une interrogation est exécutée pour chaque fonction FILTER
utilisée.
Exemple illustrant l'utilisation de CASE par rapport à FILTER
Dans cet exemple, un utilisateur demande un rapport qui montre les profits par trimestre et par UGS de produit sélectionné. Les UGS sont regroupées en 12 catégories. Les produits suivants sont affectés à la catégorie Other Cola : Cola, Diet Cola et Shared Diet Cola.
.jpg
Voici l'interrogation logique de l'énoncé 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
Il n'y a pas de regroupement basé sur l'énoncé CASE
. Une seule interrogation MDX est générée, avec l'énoncé CASE
traité par 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]
L'énoncé CASE
est exécuté sur le serveur BI, ce qui se traduit par le réglage database 0:0,0
pour la base de données :
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]
Vous pouvez également utiliser un filtre sur la mesure de profits pour n'extraire que les membres LOB requis. Dans ce scénario, vous créez trois mesures avec les filtres correspondants appliqués.
Voici l'interrogation logique de l'énoncé 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
Dans ce scénario, trois interrogations sont générées, une pour chaque filtre, et vous rencontrez des problèmes de performance.
Interrogation 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] ]]
Interrogation 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] ]]
Interrogation 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]
Exemple avec filtre de produit appliqué
Une meilleure approche consiste à inclure la colonne Product (Produit) dans le rapport avec une seule colonne Mesure sans filtre. Puis à créer un filtre incluant les produits requis. Si vous voulez regrouper les produits en différentes catégories, utilisez un énoncé CASE
. Dans ce scénario, une seule interrogation MDX est générée avec les rangées filtrées. Même si l'énoncé CASE
est appliqué par Oracle Analytics, elle utilise le sous-jeu de données et non l'ensemble des enregistrements.
Voici un autre scénario dans lequel les énoncés CASE
posent des problèmes de performance.
Un développeur applique un énoncé CASE
pour renommer les marques, et une invite du tableau de bord permet aux utilisateurs de sélectionner la marque .
.jpg
.jpg
L'énoncé CASE
n'étant pas pris en charge dans l'interrogation MDX, le filtre sur Brand2
ne peut pas être appliqué dans l'interrogation MDX. Toutes les marques sont sélectionnées, ce qui n'est pas optimisé.
.jpg
Dans ce type de scénario, Oracle recommande de supprimer l'énoncé CASE
et de renommer les membres dans la base de données ou de créer des alias.