Çok Boyutlu Veritabanı Sorgularının Performansını Ayarlama

Oracle Analitik'te veri kaynağı olarak çok boyutlu bir veritabanı kullandığınızda performans sorunları yaşayabilirsiniz ve bu da ideal olmayan çok boyutlu ifade (MDX) sorgularının oluşturulmasına neden olur.

Tasarımı değiştirerek Oracle Analitik'in oluşturduğu MDX sorgularını iyileştirebilirsiniz. Bunun sadece rapor performansınız üzerinde değil, aynı zamanda veritabanında kullanılan kaynakların hacmi üzerinde de büyük etkisi olabilir. Desteklenen veya desteklenmeyen fonksiyonları nasıl kullandığınız, oluşturulan MDX sorgularını ve dolayısıyla performansı büyük ölçüde etkiler.

Her kullanım senaryosu benzersiz olduğundan, geliştirme ekibiniz seçenekleri gözden geçirmeli, Oracle Analitik sorgu günlüklerini analiz etmeli ve kullanım senaryonuz için en iyi çözümü seçmelidir.

Bu konu; ağlar, tarayıcılar veya rapor sunumu gibi altyapınızın neden olduğu performans sorunlarını ele almaz.

Metodoloji

Oracle performansı artırmak için aşağıdaki görevleri gerçekleştirmenizi önerir. Oracle Analitik'in oluşturduğu sorgu günlüklerinin yanı sıra MDX sorgu yapısını da anlamanız önemlidir.

  • Oluşturulan MDX sorgularını basitleştirin.
  • Oluşturulan MDX sorgularının sayısını azaltın.
  • MDX sorgusunda en uygun filtrelerin ve seçimlerin uygulandığına emin olun.
  • Çok boyutlu veritabanında veritabanı yöneticisiyle performans ayarı yapın ve kaynak veritabanının hala kötü performans gösterme nedenini doğrulayın.
  • Analizi veritabanı yöneticisinin geri bildirimine göre değiştirin.

Seçim Adımları Optimizasyonu

Seçim adımlarını optimize ettiğinizde MDX sorgularını basitleştirebilir, oluşturulan MDX sorgularının sayısını azaltabilir ve performansı artırabilirsiniz.

Aşağıdaki şekil, optimize edilmiş ve optimize edilmemiş seçim adımlarının karşılaştırılmasının bir örneğini gösterir.

GUID-43E6F348-B14C-40DC-8C21-DA34DAE44344-default.jpg açıklaması aşağıdadır
.jpg'' çiziminin açıklaması

CASE Komutları

CASE komutu fonksiyonelliği MDX sorgularında desteklenmez ve bunun her zaman Oracle Analitik'te uygulanması gerekir. CASE komutlarıyla ilgili olarak açıklanan mantık, MDX sorgularında desteklenmeyen çoğu fonksiyon için geçerlidir (if null vb.).

CASE komutlarını kullanmanın avantajları ve dezavantajları vardır. Rapor formüllerine CASE komutlarını eklediğinizde bunlar MDX sorgusuna dahil edilmez. Bu, MDX sorgusunu basitleştirebilir ve performansı artırabilir. Ancak bunun sonucunda etkili bir şekilde filtreleme yapamazsınız ve bu, sorgunun gerekenden daha fazla kayıt döndürebileceği anlamına gelir.

CASE komutu fonksiyonelliğinin kullanımına ilişkin kısıtlamalar şunlardır:

  • CASE komutu birden fazla üyeyi birleştirmiyorsa, komutta kullanılan temel sütunun sorguya ve görünümlere ayrı bir gizli sütun olarak dahil edilmesi gerekir.
  • CASE komutu birden fazla üyeyi birleştiriyorsa, temel sütun toplama düzeyini etkilemeden görünüme dahil edilemez. Bu durum geçerliyse:
    • Ölçünün toplama kuralı Harici Toplama değilse temel sütunun sorgudan hariç tutulması gerekir.
    • Ölçünün toplama kuralı Harici Toplama ise temel sütunun sorguya dahil edilmesi ve görünümden hariç tutulması gerekir. Ölçünün toplama kuralını öndeğerden basit bir dahili toplama kuralına (SUM, MAX, MIN) dönüştürmelisiniz. Bu sadece üyeleri birleştirmek için dahili toplama kuralı kullanıldığında ve doğru sonuçlar sağladığında işe yarar.

FILTER Fonksiyonu

CASE komutu fonksiyonelliğinin aksine, FILTER fonksiyonu yürütülmek üzere veritabanına gönderilebilir.

Rapor formüllerinde FILTER fonksiyonunu kullanmanın temel avantajı, seçimin MDX sorgusunda uygulanması ve veritabanından hesaplanıp alınan veri hacminin azaltılmasıdır.

FILTER fonksiyonunu kullanmanın temel dezavantajı, yürütülen MDX sorgularının sayısını artırabilmesidir. Öndeğer olarak, kullanılan her FILTER fonksiyonu için bir sorgu yürütülür.

CASE - FILTER Karşılaştırma Örneği

Bu örnekte, kullanıcı üç aylık döneme göre karı ve seçili ürün stok tutma birimini gösteren bir rapor ister. Ayrıca stok tutma birimleri 12 kategoride gruplanmıştır. Diğer Kola kategorisine şu büyük nesnenin ürünleri atanmıştır: Kola, Diyet Kola ve Paylaşılan Diyet Kola.

GUID-7198F143-54E6-4A48-9579-96624936A94D-default.jpg açıklaması aşağıdadır
.jpg'' çiziminin açıklaması

CASE komutu mantıksal sorgusu:

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 komutunu temel alan bir gruplama yok. Oracle Analitik tarafından işlenen CASE komutuyla basit bir MDX sorgusu oluşturulur:

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 komutu İş Zekası Sunucusu'nda yürütülür ve bu veritabanı ayarının database 0:0,0 olarak ayarlanmasıyla görülür:

 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]

Alternatif olarak, sadece gerekli büyük nesne üyelerini almak için kar metriğine göre bir filtre kullanabilirsiniz. Bu senaryoda ilgili filtrelerin uygulandığı üç metrik oluşturursunuz.

FILTER komutu mantıksal sorgusu:

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

Bu senaryoda her filtre için bir adet olmak üzere üç sorgu oluşturulur ve performans sorunlarıyla karşılaşırsınız.

Sorgu 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]

]]

Sorgu 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]

]]

Sorgu 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]

Ürün Filtresi Uygulanan Örnek

Ürün sütununu filtre olmadan tek bir ölçü sütunuyla rapora dahil etmek daha iyi bir yaklaşımdır. Daha sonra gerekli ürünleri içeren bir filtre oluşturun. Ürünleri farklı kategoriler halinde gruplamak istiyorsanız CASE komutu kullanın. Bu senaryoda, filtrelenen satırlarla tek bir MDX sorgusu oluşturulur ve CASE komutu Oracle Analitik tarafından uygulansa bile tüm kayıtları değil, verilerin alt kümesini kullanır.

CASE komutlarının performans sorunlarına neden olduğu başka bir senaryo aşağıda verilmiştir.

Bir geliştirici, markaları yeniden adlandırmak için bir CASE komutu uygular ve bir kumanda tablosu bilgi istemi kullanıcıların markayı seçmesini sağlar.

GUID-56356AA9-2AF6-4A67-8ADD-FC4F7F70306C-default.jpg açıklaması aşağıdadır
.jpg'' çiziminin açıklaması

GUID-E63719C8-9936-412B-8228-F20E8F048C46-default.jpg açıklaması aşağıdadır
.jpg'' çiziminin açıklaması

CASE komutu MDX'te desteklenmediğinden, Brand2 üzerindeki filtre MDX sorgusunda uygulanamaz. Tüm markalar seçilidir ve bu optimize edilmemiştir.

GUID-6BE1F274-8257-4E31-8D42-406357A07B2A-default.jpg açıklaması aşağıdadır
.jpg'' çiziminin açıklaması

Bu senaryo tipinde, Oracle CASE komutunu kaldırmanızı ve veritabanındaki üyeleri yeniden adlandırmanızı ya da diğer adlar oluşturmanızı önerir.