כאשר אתה משתמש במסד נתונים רב-ממדי כמקור נתונים ב-Oracle Analytics, אתה עלול להיתקל בבעיות ביצועים שגורמות ליצירת שאילתות לא אופטימליות של ביטוי רב-ממדי (MDX).
על-ידי שינוי העיצוב, תוכל לשפר את שאילתות ה-MDX המופקות ב-Oracle Analytics. לפעולה זו עשויה להיות השפעה עצומה, לא רק על ביצועי הדוחות שלך אלא גם על נפח המשאבים שבהם נעשה שימוש במסד הנתונים. אופן השימוש בפונקציות נתמכות או לא נתמכות משפיע מאוד על שאילתות ה-MDX שנוצרות ולכן על הביצועים.
מכיוון שכל תרחיש שימוש הוא ייחודי, על צוות הפיתוח לבחון אפשרויות אלו, לנתח את יומני השאילתות של Oracle Analytics, ולבחור את הפתרון הטוב ביותר עבור תרחיש השימוש שלך.
נושא זה לא מתייחס לבעיות ביצועים שנגרמו בגלל התשתית שלך, כגון דפדפני הרשת או מצגת הדוח.
מתודולוגיה
Oracle ממליצה לבצע את המשימות הבאות כדי להגביר את הביצועים. חשוב שתבין את מבנה השאילתות של MDX וכן את יומני השאילתות ש-Oracle Analytics מייצרת.
אופטימיזציה של שלבי הבחירה
כאשר תבצע אופטימיזציה של שלבי בחירה תוכל לפשט את שאילתות ה-MDX, להפחית את מספר שאילתות ה-MDX המופקות, ולהגביר את הביצועים.
האיור הבא מציג דוגמה להשוואה של שלבי בחירה אופטימליים ולא אופטימליים.

.jpg
משפטי CASE
הפונקציונליות של משפט CASE אינה נתמכת בשאילתות MDX ויש תמיד להחיל אותה ב-Oracle Analytics. הלוגיקה המוסברת בפרק זה לגבי משפטי CASE תקפה לרוב הפונקציות שאינן נתמכות בשאילתות MDX (אם null, וכן הלאה).
ישנם יתרונות וחסרונות בעת שימוש במשפטי CASE. כאשר אתה כולל משפטי CASE בנוסחאות דוח, הם לא נכללות בשאילתת MDX. זה יכול לפשט את שאילתת ה-MDX ולשפר את הביצועים. עם זאת, הפשרה היא שאינך יכול לסנן ביעילות רבה, מה שאומר שהשאילתא עשויה להחזיר יותר רשומות מהנדרש.
להלן הגבלות ל שימוש בפונקציונליות של משפט CASE:
CASE לא משלב מספר איברים, עמודת הבסיס המשמשת במשפט חייבת להיות כלולה בשאילתא ובתצוגות כעמודה נפרדת נסתרת.CASE משלב מספר איברים, אי אפשר לכלול את עמודת הבסיס בתצוגה מבלי להשפיע על רמת הסכימה. במקרה זה:
SUM, MAX, MIN). זה עובד רק אם כלל הסכימה הפנימי משמש לשילוב איברים ונותן תוצאות נכונות.פונקציית FILTER
שלא כמו משפט הCASE, ניתן לשלוח את פונקציית הFILTER למסד הנתונים לצורך ביצוע.
היתרון העיקרי של שימוש בפונקציית הFILTER בנוסאות דוח הוא שהבחירה מיושמת בשאילתת ה-MDX ונפח הנתונים המחושבים ומאוחזרים ממסד הנתונים מצטמצם.
החיסרון העיקרי של שימוש בפונקציית הFILTER הוא שהיא עשויה להגדיל את מספר שאילתות MDX שיבוצעו. לפי ברירת המחדל, מתבצעת שאילתא אחת לכל פונקציית FILTER שבה נעשה שימוש.
דוגמה של CASE לעומת FILTER
בדוגמה זו, המשתמש מבקש דוח שמראה רווח לפי רבעון ויחידת שמירת מלאי של מוצר נבחר. בנוסף, יחידות שמירת המלאי מקובצות יחד בשתיים-עשרה קטגוריות. לקטגוריה "קולה אחרת" הוקצו המוצרים הבאים של תחום פעילות עסקית: קולה, קולה דיאט, קולה דיאט משותפת.

.jpg
הנה השאילתא הלוגית של משפט 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 פשוטה, כאשר NAPY 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]לחלופין, תוכל להשתמש במסנן כנגד מדד הרווח כדי לאחזר את איברי תחום הפעילות העסקית בלבד. בתרחיש זה, יוצרים 3 מדדים כשמחילים את המסננים המתאימים.
הנה השאילתא הלוגית של משפט 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 יחידה עם השורות שסוננו ולמרות ש-Oracle Analytics יחיל את משפט הCASE, המשפט יעשה שימוש בתת-סל של נתונים ולא בכל הרשומות.
הנה תרחיש אחר שבו משפטי CASE גורמים לבעיות בביצועים.
מפתח מחיל משפטCASE כדי לשנות שמות מותגים, ומנחה לוח המידע מרשה למשתמשים לבחור את המותג.

.jpg

.jpg
כיוון שמשפט הCASE אינו נתמך ב-MDX, לא ניתן להחיל את המסנן על Brand2 בשאילתת ה-MDX. נבחרים כל המותגים, וזה לא ממוטב.

.jpg
בסוג זה של תרחיש, Oracle ממליצה להסיר את משפט ה-CASE ולשנות את שמות האיברים במסד הנתונים או ליצור כינויים.