ปรับแต่งประสิทธิภาพการสืบค้นฐานข้อมูลแบบหลายไดเมนชัน

เมื่อคุณใช้ฐานข้อมูลแบบหลายไดเมนชันเป็นที่มาข้อมูลใน Oracle Analytics คุณอาจประสบปัญหาด้านประสิทธิภาพซึ่งทำให้เกิดการสืบค้น Suboptimal Multidimensional Expression (MDX) ที่สร้างโดยมีประสิทธิภาพลดลง

คุณสามารถปรับปรุงการสืบค้น MDX ที่ Oracle Analytics สร้างขึ้นได้โดยการแก้ไขการออกแบบ การดำเนินการนี้จะส่งผลกระทบอย่างมาก ไม่เฉพาะต่อประสิทธิภาพของรายงานของคุณ แต่กับปริมาณทรัพยากรที่ใช้ในฐานข้อมูลด้วย วิธีที่คุณใช้ฟังก์ชันที่รองรับหรือไม่รองรับจะส่งผลกระทบต่อการสืบค้น MDX ที่สร้างขึ้นและประสิทธิภาพการทำงานเป็นอย่างมาก

เนื่องจากแต่ละกรณีการใช้งานไม่ซ้ำกัน ทีมพัฒนาของคุณควรตรวจดูตัวเลือกต่างๆ ให้วิเคราะห์ล็อกการสืบค้น Oracle Analytics และเลือกทางแก้ปัญหาที่ดีที่สุดสำหรับกรณีการใช้งานของคุณ

หัวข้อนี้ไม่แสดงปัญหาด้านประสิทธิภาพที่เกิดจากโครงสร้างพื้นฐานของคุณ เช่น เน็ตเวิร์ก เบราเซอร์ หรือการนำเสนอรายงาน

วิธีการ

Oracle แนะนำให้คุณดำเนินการกับงานต่อไปนี้เพื่อเพิ่มประสิทธิภาพ สิ่งสำคัญคือคุณต้องเข้าใจโครงสร้างการสืบค้น MDX รวมถึงล็อกการสืบค้นที่ Oracle Analytics สร้างขึ้น

  • ลดความยุ่งยากของการสืบค้น MDX ที่สร้าง
  • ลดจำนวนการสืบค้น MDX ที่สร้าง
  • ตรวจสอบให้แน่ใจว่ามีการใช้ฟิลเตอร์และการเลือกที่มีประสิทธิภาพสูงในการสืบค้น MDX
  • ปรับแต่งประสิทธิภาพด้วยผู้ดูแลระบบฐานข้อมูล (DBA) ทางฐานข้อมูลแบบหลายไดเมนชัน และตรวจสอบสาเหตุที่ฐานข้อมูลที่มายังคงทำงานอย่างไม่มีประสิทธิภาพ
  • แก้ไขการวิเคราะห์ตามข้อเสนอแนะของ DBA

การออปติไมซ์ขั้นตอนการเลือก

คุณคุณออปติไมซ์ขั้นตอนการเลือก คุณจะสามารถลดความยุ่งยากของการสืบค้น MDX, ลดจำนวนการสืบค้น MDX ที่สร้าง และเพิ่มประสิทธิภาพ

รูปต่อไปนี้แสดงตัวอย่างการเปรียบเทียบขั้นตอนการเลือกที่ออปติไมซ์และที่ไม่ได้ออปติไมซ์

คำอธิบาย GUID-43E6F348-B14C-40DC-8C21-DA34DAE44344-default.jpg มีดังนี้
.jpg

คำสั่ง 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

ในตัวอย่างนี้ ผู้ใช้ขอรายงานที่แสดงผลกำไรแยกตามไตรมาสและ SKU ผลิตภัณฑ์ที่เลือก นอกจากนี้ SKU ยังได้รับการจัดกลุ่มเข้าด้วยกันเป็น 12 ชนิด ชนิด Other Cola มีผลิตภัณฑ์ของ LOB ที่ระบุไว้ดังต่อไปนี้: Cola, Diet Cola และ Shared Diet Cola

คำอธิบาย GUID-7198F143-54E6-4A48-9579-96624936A94D-default.jpg มีดังนี้
.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 ทั่วไปจะถูกสร้างขึ้น โดยมีคำสั่ง 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]

หรือคุณสามารถใช้ฟิลเตอร์กับเมตริคผลกำไรเพื่อดึงข้อมูลสมาชิก LOB ที่จำเป็นเท่านั้น ในสถานการณ์นี้ คุณสร้างเมตริค สามรายการที่มีการใช้ฟิลเตอร์ที่เกี่ยวข้อง

นี่คือการสืบค้นแบบลอจิคัลของคำสั่ง 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 ในการเปลี่ยนชื่อตราสินค้า และผู้ใช้สามารถใช้พรอมต์ของแผงข้อมูลในการเลือกตราสินค้าได้

คำอธิบาย GUID-56356AA9-2AF6-4A67-8ADD-FC4F7F70306C-default.jpg มีดังนี้
.jpg

คำอธิบาย GUID-E63719C8-9936-412B-8228-F20E8F048C46-default.jpg มีดังนี้
.jpg

เนื่องจากคำสั่ง CASE ไม่ได้รับการรับรองใน MDX จึงไม่สามารถใช้การฟิลเตอร์ Brand2 ในการสืบค้น MDX ได้ เลือกตราสินค้าทั้งหมดแล้ว และไม่ได้รับการออปติไมซ์

คำอธิบาย GUID-6BE1F274-8257-4E31-8D42-406357A07B2A-default.jpg มีดังนี้
.jpg

ในสถานการณ์นี้ Oracle แนะนำให้คุณย้ายคำสั่ง CASE ออก และเปลี่ยนชื่อสมาชิกในฐานข้อมูล หรือสร้างชื่อแทน