用於分析查詢的 MDX 與 SQL 的好例子
**在進行分析查詢時,任何人都可以向我展示 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]