Olap

用於分析查詢的 MDX 與 SQL 的好例子

  • December 28, 2016

**在進行分析查詢時,任何人都可以向我展示 MDX 相對於正常 SQL 的優勢的一個很好的例子嗎?**我想將 MDX 查詢與給出相似結果的 SQL 查詢進行比較。

維基百科說

雖然可以將其中一些轉換為傳統 SQL,但即使對於非常簡單的 MDX 表達式,也經常需要合成笨拙的 SQL 表達式。

但是既沒有引用也沒有例子。我完全清楚底層數據必須以不同的方式組織,並且 OLAP 每次插入都需要更多的處理和儲存。(我的建議是從 Oracle RDBMS 遷移到Apache Kylin + Hadoop

**背景:**我試圖說服我的公司,我們應該查詢 OLAP 數據庫而不是 OLTP 數據庫。大多數 SIEM 查詢大量使用分組、排序和聚合。除了性能提升之外,我認為 OLAP (MDX) 查詢會比等效的 OLTP SQL 更簡潔、更容易讀/寫。一個具體的例子可以說明這一點,但我不是 SQL 專家,更不用說 MDX ……


如果有幫助,以下是針對過去一周發生的防火牆事件的範例 SIEM 相關 SQL 查詢:

SELECT   'Seoul Average' AS term, 
        Substr(To_char(idate, 'HH24:MI'), 0, 4) 
                 || '0'        AS event_time , 
        Round(Avg(tot_accept)) AS cnt 
FROM     ( 
               SELECT                     * 
               FROM   st_event_100_#yyyymm-1m# 
               WHERE  idate BETWEEN trunc(sysdate, 'iw')-7 AND trunc(sysdate, 'iw')-3 #stat_monitor_group_query#
               UNION ALL 
               SELECT * 
               FROM   st_event_100_#yyyymm# 
               WHERE  idate BETWEEN trunc(sysdate, 'iw')-7 AND trunc(sysdate, 'iw')-3 #stat_monitor_group_query# ) pm
GROUP BY substr(to_char(idate, 'HH24:MI'), 0, 4) 
                 || '0' 
UNION ALL 
SELECT   'today' AS term , 
        substr(to_char(idate, 'HH24:MI'), 0, 4) 
                 || '0'        AS event_time , 
        round(avg(tot_accept)) AS cnt 
FROM     st_event_100_#yyyymm# cm 
WHERE    idate >= trunc(sysdate) #stat_monitor_group_query# 
GROUP BY substr(to_char(idate, 'HH24:MI'), 0, 4) 
                 || '0' 
ORDER BY term DESC, 
        event_time ASC

MDX並且在查詢和分別SQL時絕不相同,甚至通常甚至不具有可比性。您不能使用 MDX 查詢現有的關係數據庫。multidimensional``relational databases

使用多維模型並使用 MDX 查詢它的主要優點是您正在查詢預聚合數據,並且 MDX 已優化為以統計方式而不是關係方式查詢。您不再查詢行和表來生成平面結果集,而是使用元組和集合來切片和聚合多維多維數據集。

可以這樣想:如果您使用 SQL 查詢來獲取特定項目組的總銷售額,則需要編寫一個查詢來匯總項目組中所有項目的所有發票行。如果您使用多維數據集並在項目組級別上進行聚合,則在處理期間計算結果並為每個項目組儲存聚合,從而使查詢即時進行。

多維和 MDX 是與基於關係集的 SQL 完全不同的概念。

您的範例可能會變得更簡單,因為您將在數據載入過程中進行日期解析等轉換,並且您上個月的比較可能是calculated measure. 你的首爾平均水平和今天可能是calculated members

如果您的多維數據集設計得很好,可以滿足您的要求,我相信您可以對範例的數據集進行切片和切塊,甚至不需要編寫查詢,而是在數據透視表或其他分析工具中進行。

再說一遍,沒有“只是在 MDX 中重寫 SQL”。正確地做這件事需要相當多的知識和不同的心態。想想維恩圖而不是結果集。

為了給您提供一個使用 Adventureworks 數據庫的範例,假設需要在自行車類別中按客戶列出銷售訂單的數量。

如果您使用 SQL 執行此操作,則需要編寫一個查詢來計算銷售訂單的數量,其中包含一條恰好屬於自行車類別的產品,並將其連接到客戶表中,因此這將成為一個相當複雜的查詢.

-- need distinct count, we're counting orders, not order lines
SELECT count(DISTINCT soh.salesorderid)
   ,pers.FirstName + ' ' + pers.LastName
FROM sales.SalesOrderDetail sod
-- we need product details to get to the category
INNER JOIN Production.Product p ON sod.ProductID = p.ProductID
-- but we need to pass via subcategories
INNER JOIN Production.ProductSubcategory psc ON p.ProductSubcategoryID = psc.ProductSubcategoryID
-- we finally get to the category
INNER JOIN Production.ProductCategory pc ON psc.ProductCategoryID = pc.ProductCategoryID
-- we also need the headers because that's where the customer is stored
INNER JOIN sales.SalesOrderHeader soh ON sod.SalesOrderID = soh.SalesOrderID
-- finally the customer, but we don't have his name here
INNER JOIN sales.Customer c ON soh.CustomerID = c.CustomerID
-- customers
INNER JOIN Person.Person pers ON c.PersonID = pers.BusinessEntityID
-- filter on bikes
WHERE pc.Name = 'bikes'
-- but the customers table doesn't contain the concatenated name
GROUP BY pers.FirstName + ' ' + pers.LastName;

在 MDX 中(如果您的多維數據集針對此要求設計得很好),您可以直接編寫,因為邏輯和復雜性已經轉移到其他地方:

SELECT [Measures].[Internet Order Count] ON COLUMNS,
[Customer].[Customer].Members ON ROWS
FROM [Adventure Works]
WHERE [Product].[Product Categories].[Category].[Bikes]

引用自:https://dba.stackexchange.com/questions/138311