Όταν χρησιμοποιείτε μια πολυδιάστατη βάση δεδομένων ως πηγή δεδομένων στο Oracle Analytics, μπορεί να αντιμετωπίσετε ζητήματα απόδοσης που οδηγούν στη δημιουργία ερωτημάτων πολυδιάστατων εκφράσεων (MDX) τα οποία δεν είναι τα βέλτιστα.
Με την τροποποίηση της σχεδίασης, μπορείτε να βελτιώσετε τα ερωτήματα MDX που δημιουργεί το Oracle Analytics. Αυτό μπορεί να έχει τεράστια επίδραση, όχι μόνο στην απόδοση των αναφορών σας, αλλά και στον όγκο των πόρων που χρησιμοποιούνται στη βάση δεδομένων. Ο τρόπος που χρησιμοποιείτε τις υποστηριζόμενες ή μη υποστηριζόμενες συναρτήσεις επηρεάζει πολύ σημαντικά τα ερωτήματα MDX που παράγονται και συνεπώς την απόδοση.
Επειδή κάθε περίπτωση είναι μοναδική, η ομάδα προγραμματιστών σας πρέπει να εξετάσει τις επιλογές, να αναλύσει τα αρχεία καταγραφής ερωτημάτων του Oracle Analytics και να επιλέξει τη βέλτιστη λύση για τη δική σας περίπτωση χρήσης.
Αυτό το θέμα δεν καλύπτει ζητήματα απόδοσης που προκλήθηκαν από την υποδομή σας, όπως τα δίκτυα, τα προγράμματα περιήγησης ή την παρουσίαση αναφορών.
Μεθοδολογία
Η Oracle συνιστά να ολοκληρώσετε τις παρακάτω εργασίες για να αυξήσετε την απόδοση. Είναι σημαντικό να κατανοήσετε τη δομή των ερωτημάτων MDX καθώς και τα αρχεία καταγραφής ερωτημάτων που παράγει το Oracle Analytics.
Βελτιστοποίηση βημάτων επιλογής
Όταν βελτιστοποιείτε τα βήματα επιλογής, μπορείτε να απλουστεύσετε τα ερωτήματα MDX, να μειώσετε τον αριθμό των ερωτημάτων MDX που δημιουργούνται και να αυξήσετε την απόδοση.
Το ακόλουθο σχήμα παρουσιάζει ένα παράδειγμα μιας σύγκρισης των βελτιστοποιημένων και μη βελτιστοποιημένων βημάτων επιλογής.
Δηλώσεις CASE
Η λειτουργικότητα δηλώσεων CASE
δεν υποστηρίζεται στα ερωτήματα MDX και πρέπει να εφαρμόζεται πάντα στο Oracle Analytics. Η λογική που εξηγείται σε αυτήν την ενότητα αναφορικά με τις δηλώσεις CASE
ισχύει για τις περισσότερες συναρτήσεις που δεν υποστηρίζονται στα ερωτήματα MDX (if null
και ούτω καθεξής).
Υπάρχουν πλεονεκτήματα και μειονεκτήματα όταν χρησιμοποιείτε τις δηλώσεις CASE
. Όταν συμπεριλαμβάνετε δηλώσεις CASE
σε τύπους αναφοράς, αυτές δεν περιλαμβάνονται στο ερώτημα MDX. Αυτό μπορεί να απλοποιήσει το ερώτημα MDX και να βελτιώσει την απόδοση. Ωστόσο, η αντιστάθμιση είναι ότι δεν μπορείτε να φιλτράρετε εξίσου αποτελεσματικά, πράγμα που σημαίνει ότι το ερώτημα ενδέχεται να επιστρέψει περισσότερες εγγραφές από ό, τι είναι απαραίτητο.
Οι ακόλουθοι είναι περιορισμοί για τη χρήση της λειτουργικότητας δηλώσεων CASE
:
CASE
δεν συνδυάζει πολλά μέλη, η βασική στήλη που χρησιμοποιείται στη δήλωση θα πρέπει να περιλαμβάνεται στο ερώτημα και τις προβολές ως κρυφή ξεχωριστή στήλη.CASE
συνδυάζει πολλά μέλη, η βασική στήλη δεν μπορεί να περιλαμβάνεται στην προβολή χωρίς να επηρεάζεται το επίπεδο συνάθροισης. Σε αυτήν την περίπτωση:
SUM
, MAX
, MIN
). Αυτό λειτουργεί μόνο αν ο κανόνας εσωτερικής συνάθροισης χρησιμοποιείται για τον συνδυασμό μελών και παρέχει σωστά αποτελέσματα.Συνάρτηση FILTER
Σε αντίθεση με τη λειτουργικότητα της δήλωσης CASE
, η συνάρτηση FILTER
μπορεί να σταλεί στη βάση δεδομένων για εκτέλεση.
Το κύριο πλεονέκτημα της χρήσης της συνάρτησης FILTER
σε τύπους αναφορών είναι ότι η επιλογή εφαρμόζεται στο ερώτημα MDX και ο όγκος δεδομένων που υπολογίζεται και ανακτάται από τη βάση δεδομένων είναι μειωμένος.
Το κύριο μειονέκτημα της χρήσης της συνάρτησης FILTER
είναι ότι μπορεί να αυξήσει τον αριθμό των ερωτημάτων MDX που εκτελούνται. Από προεπιλογή, εκτελείται ένα ερώτημα για κάθε συνάρτηση FILTER
που χρησιμοποιείται.
Παράδειγμα CASE έναντι FILTER
Σε αυτό το παράδειγμα, ένας χρήστης ζητά μια αναφορά που δείχνει το κέρδος ανά τρίμηνο και την επιλεγμένη ΜΔΑ προϊόντος. Επιπλέον, οι ΜΔΑ είναι ομαδοποιημένες σε 12 κατηγορίες. Στην κατηγορία "Other Cola" έχουν αντιστοιχιστεί τα ακόλουθα προϊόντα του τομέα επιχείρησης: Cola, Diet Cola και Shared Diet Cola.
Ορίστε το λογικό ερώτημα δήλωσης 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
Δεν υπάρχει ομαδοποίηση με βάση τη δήλωση CASE
. Παράγεται ένα απλό ερώτημα MDX, με τη δήλωση CASE
να υποβάλλεται σε επεξεργασία από το 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
εκτελείται στον BI Server και αυτό φαίνεται από τη ρύθμιση βάσης δεδομένων που έχει οριστεί σε 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]
Εναλλακτικά, μπορείτε να χρησιμοποιήσετε ένα φίλτρο με βάση το μέτρο κέρδους για να ανακτήσετε μόνο τα απαιτούμενα μέλη του τομέα επιχείρησης. Σε αυτό το σενάριο, δημιουργείτε τρεις δείκτες μέτρησης με εφαρμοσμένα τα αντίστοιχα φίλτρα.
Ορίστε το λογικό ερώτημα δήλωσης 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
Σε αυτό το σενάριο, δημιουργούνται τρία ερωτήματα, ένα για κάθε φίλτρο, και έχετε ζητήματα απόδοσης.
Ερώτημα 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] ]]
Ερώτημα 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] ]]
Ερώτημα 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]
Παράδειγμα εφαρμογής φίλτρου προϊόντος
Μια καλύτερη προσέγγιση είναι να συμπεριλάβετε τη στήλη προϊόντος στην αναφορά με μια στήλη μοναδικού μέτρου χωρίς φίλτρο. Στη συνέχεια, δημιουργήστε ένα φίλτρο που περιλαμβάνει τα απαιτούμενα προϊόντα. Αν θέλετε να ομαδοποιήσετε τα προϊόντα σε διαφορετικές κατηγορίες, χρησιμοποιήστε μια δήλωση CASE
. Σε αυτό το σενάριο, δημιουργείται ένα μεμονωμένο ερώτημα MDX με τις φιλτραρισμένες σειρές και παρόλο που η δήλωση CASE
εφαρμόζεται από το Oracle Analytics, χρησιμοποιεί μόνο το υποσύνολο των δεδομένων και όχι όλες τις εγγραφές.
Ακολουθεί ένα άλλο σενάριο στο οποίο οι δηλώσεις CASE
προκαλούν ζητήματα απόδοσης.
Ένας προγραμματιστής εφαρμόζει μια δήλωση CASE
για να μετονομάσει επωνυμίες. ενώ ένα μήνυμα προτροπής dashboard δίνει τη δυνατότητα στους χρήστες να επιλέξουν την επωνυμία.
Επειδή η δήλωση CASE
δεν υποστηρίζεται στην MDX, το φίλτρο στο Brand2
δεν μπορεί να εφαρμοστεί στο ερώτημα MDX. Επιλέγονται όλες οι επωνυμίες και αυτό δεν είναι ένα βελτιστοποιημένο αποτέλεσμα.
Σε αυτόν τον τύπο σεναρίου, η Oracle συνιστά να καταργήσετε τη δήλωση CASE
και να μετονομάσετε τα μέλη στη βάση δεδομένων ή να δημιουργήσετε ψευδώνυμα.