כאשר אתה משתמש במסד נתונים רב-ממדי כמקור נתונים ב-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
ולשנות את שמות האיברים במסד הנתונים או ליצור כינויים.