2016-08-15 20 views
2

我想通過在關係數據庫(ROLAP)中使用星型模式來構建一個簡單的多維數據模型。爲此,我創建了一個事實表和兩個維度表。首先我複製操作源的數據並處理這些數據(一些簡化的ETL過程)。這個多維模型有什麼不對?

在我的模型中只有兩個維度:datestatus。度量:某些狀態的數量(一段時間)。

的時間維度表:

CREATE TABLE [dbo].[tbl_date_dim] ( 
    [ID][int]  IDENTITY(1,1) NOT NULL, 
    [date_key][int] NOT NULL primary key, 
    [Year][int]  NOT NULL, 
    [Month][int] NOT NULL, 
    [Day][int]  NOT NULL   
); 

有一個表 - tbl_application - 其中存儲的全部時間範圍(場VersionDate)。因此,時間維度表,我填補這一方式:

INSERT INTO [dbo].[tbl_date_dim] 
    ([date_key], 
    [Year], 
    [Month], 
    [Day]) 
(
    SELECT DISTINCT 
    CAST(YEAR(VersionDate) as VARCHAR(4)) + 
    RIGHT('00' + CAST(MONTH(VersionDate) as VARCHAR(2)) ,2) + 
    RIGHT('00' + CAST(DAY(VersionDate) as VARCHAR(2)), 2) as 'date_key', 
    YEAR(inner_data.VersionDate) as 'Year', 
    MONTH(inner_data.VersionDate) as 'Month', 
    DAY(inner_data.VersionDate)  as 'Day' 
    FROM (
     SELECT 
      VersionDate 
     FROM [dbo].[tbl_application] 
) AS inner_data 
); 

狀態維度表:我用整個現有的表tbl_applicationstatus

接下來,我創建了一個事實表。它包含用於維度表和度量的外鍵。

CREATE TABLE [dbo].[tbl_olap_fact] (
    [ID][int] IDENTITY(1,1) NOT NULL,  

    [status_id][int] NOT NULL,   // FK 
    [date_dim][int] NOT NULL,   // FK 

    [staus_name] varchar(100) NOT NULL, // Non additive measure 
    [transaction_id][int] NOT NULL,  // Additive measure 

    CONSTRAINT [PK_tbl_olap_fact] PRIMARY KEY CLUSTERED 
(
    [ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY]; 

transaction_id - 這個字段,我將聚合(狀態數)。

接下來,我添加了事實表和維表之間的關係:

ALTER TABLE [dbo].[tbl_olap_fact] ADD CONSTRAINT [FK_tbl_olap_fact_tbl_date_dim] FOREIGN KEY([date_dim]) 
REFERENCES [dbo].[tbl_date_dim] ([date_key]); 

ALTER TABLE [dbo].[tbl_olap_fact] ADD CONSTRAINT [FK_tbl_olap_fact_tbl_applicationstatus] FOREIGN KEY([status_id]) 
REFERENCES [dbo].[tbl_applicationstatus] ([ID]); 

然後我填的是事實表:

INSERT INTO [dbo].[tbl_olap_fact] 
    ([transaction_id], 
    [status_id], 
    [staus_name], 
    [date_dim]) 
(
    SELECT DISTINCT 
    core.id   as 'transaction_id', 
    core_status.ID as 'status_id', 
    core_status.name as 'status_name', 
    CAST(YEAR(core.VersionDate) as VARCHAR(4)) + 
    RIGHT('00' + CAST(MONTH(core.VersionDate) as VARCHAR(2)) ,2) + 
    RIGHT('00' + CAST(DAY(core.VersionDate) as VARCHAR(2)), 2) as 'date_dim' 
    FROM 
    [dbo].[tbl_application] as core 
     inner join tbl_applicationstatus as core_status 
     on core.ApplicationStatusID = core_status.ID 
    WHERE IsRaw = 0 
); 

由於我使用的是蒙德里安的OLAP服務器。定義多維數據庫的邏輯模型的Mondrian模式:

<Schema name="olap_schema"> 
    <Dimension type="TimeDimension" visible="true" highCardinality="false" name="Date first dim"> 
    <Hierarchy name="date_hierarchy" visible="true" hasAll="true" primaryKey="date_key" description=""> 

     <Table name="tbl_date_dim" schema="dbo"> 
     </Table> 

     <Level name="" 
      visible="true" 
      table="tbl_date_dim" 
      column="Year" 
      nameColumn="Year" 
      type="Numeric" 
      uniqueMembers="true" 
      levelType="TimeYears" 
      hideMemberIf="Never" 
      description="">   
     </Level> 

     <Level name="" 
      visible="true" 
      table="tbl_date_dim" 
      column="Month" 
      nameColumn="Month" 
      ordinalColumn="Month" 
      type="Numeric" 
      uniqueMembers="false" 
      levelType="TimeMonths" 
      hideMemberIf="Never" 
      description=""> 
     </Level> 

     <Level name="" 
      visible="true" 
      table="tbl_date_dim" 
      column="Day" 
      nameColumn="Day" 
      ordinalColumn="Day" 
      type="Numeric" 
      uniqueMembers="false" 
      levelType="TimeDays" 
      hideMemberIf="Never" 
      description=""> 
     </Level> 

    </Hierarchy> 
    </Dimension> 

    <Dimension type="TimeDimension" visible="true" highCardinality="false" name="Date second dim"> 
    <Hierarchy name="date_hierarchy" visible="true" hasAll="true" primaryKey="date_key" description=""> 
     <Table name="tbl_date_dim" schema="dbo"> 
     </Table> 

     <Level name="" 
      visible="true" 
      table="tbl_date_dim" 
      column="Year" 
      nameColumn="Year" 
      type="Numeric" 
      uniqueMembers="true" 
      levelType="TimeYears" 
      hideMemberIf="Never" 
      description=""> 
     </Level> 

     <Level name="" 
      visible="true" 
      table="tbl_date_dim" 
      column="Month" 
      nameColumn="Month" 
      ordinalColumn="Month" 
      type="Numeric" 
      uniqueMembers="false" 
      levelType="TimeMonths" 
      hideMemberIf="Never" 
      description=""> 
     </Level> 

     <Level name="" 
      visible="true" 
      table="tbl_date_dim" 
      column="Day" 
      nameColumn="Day" 
      ordinalColumn="Day" 
      type="Numeric" 
      uniqueMembers="false" 
      levelType="TimeDays" 
      hideMemberIf="Never" 
      description=""> 
     </Level> 

    </Hierarchy> 
    </Dimension> 

    <Dimension type="StandardDimension" visible="true" highCardinality="false" name="Status dimension"> 
    <Hierarchy name="status_hierarchy" visible="true" hasAll="true" primaryKey="ID" description=""> 
     <Table name="tbl_applicationstatus" schema="dbo"> 
     </Table> 
     <Level name="" 
      visible="true" 
      table="tbl_applicationstatus" 
      column="Name" 
      nameColumn="Name" 
      type="String" 
      uniqueMembers="true" 
      levelType="Regular" 
      hideMemberIf="Never" 
      description=""> 
     </Level> 
    </Hierarchy> 
    </Dimension> 

    <Cube name="enrollment_cube" caption="" visible="true" description="" cache="true" enabled="true"> 
    <Table name="tbl_olap_fact" schema="dbo"> 
    </Table> 

    <DimensionUsage source="Date first dim" name="X axis" caption="" visible="true" foreignKey="date_dim" highCardinality="false"> 
    </DimensionUsage> 

    <DimensionUsage source="Date second dim" name="Y axis" caption="" visible="true" foreignKey="date_dim" highCardinality="false"> 
    </DimensionUsage> 

    <DimensionUsage source="Status dimension" name="Z axis" caption="" visible="true" foreignKey="status_id" highCardinality="false"> 
    </DimensionUsage> 

    <Measure name="TotalCount" column="transaction_id" aggregator="count" caption="Total" visible="true"> 
    </Measure> 

    </Cube> 

</Schema> 

作爲使用Saiku Analytics的OLAP客戶端。

enter image description here

基本上,我得到正確的數據 - 但它不太清楚。例如,我用來填充事實表的方式是否正確?我是否正確構建ETL過程?這是一個測試模式,我在構建數據倉庫和多維模型方面做了一些實驗。

我將非常感激這些信息。謝謝大家。

回答

1

此處聲明:我從未使用過Mondrian,我在這裏給出的建議是通用的,堅持接近Kimball的做事方式。如果蒙德里安需要對模式進行一些特殊的更改,那就去做吧。


tbl_date_dim

這是一個良好的開端 - 日期維度是至關重要的。你可能會發現你還需要一個單獨的時間維度(例如,如果你想按小時來看待事物)。

我會對此做出刪除ID列。它的用途是什麼?每個YYYYMMDD值都是唯一的,這裏的標準模式就是簡單地使用它作爲該表的代理鍵。

您可能會發現您想要爲此表添加更多列;現在,我會建議添加一個包含實際日期的日期列,因爲這是此維度的商業關鍵。您應始終在每個維度中都有代理鍵和業務鍵。

如果您還不熟悉這個術語,請閱讀商業密鑰的概念 - 它基本上是一個有意義的名稱,您的組織在引用特定維度成員時通常會使用某種名稱。人們經常犯這樣一個錯誤:使用無意義的代碼或源代碼系統中無用的縮寫,但這些都應該避免。

我建議以不同的方式填充tbl_date_dim。當然,你現在這樣做的方式現在可以工作,但是你的日期維度最終會被許多其他表引用,你可能會發現它缺少你需要的日期。標準的解決方案就是編寫腳本,甚至將電子表格彙總並導入,並在過去和未來中包含合適的日期範圍。它從來沒有那麼大,所以尺寸並不是真正的問題。如果你想編寫腳本,你應該能夠通過一些搜索找到爲你工作的腳本。

tbl_applicationstatus

很難在這,你不顯示DDL發表評論。不過,你可能不應該使用整個源表。確保在數據倉庫中創建了一個代理鍵(一個標識列很好,將其命名爲application_status_key)和業務鍵。這可能是status_name。

tbl_olap_fact

事實表應該是在相同的晶粒的一種或多種措施,和外鍵維度表。理解穀物是至關重要的,你應該思考穀物是什麼,然後給出一個反映它的有意義的名字。如果你的事實將會有更多與交易有關的措施,那麼tbl_transaction_fact可能是一個好名字,例如。

由於您沒有解釋tbl_application源表中有哪些數據,因此您在此處測量的內容有點不清楚,但看起來您似乎正在計算執行某些應用程序狀態已設置?請注意,您實際上並沒有任何添加劑測量值;一個加法度量是可以總結的東西 - 金錢數量,項目數量等。

如果你只是以此爲例,我強烈建議你首先考慮一個你想要你的立方體的問題回答哪些東西是附加的(即,如果您的應用程序具有貨幣價值,那麼就是「一月份創建的所有應用程序的價值多少?」),然後建模一些可以回答該問題的東西。

你絕對可以做一個計數,但是爲源導入transaction_id值可能不是必要的 - 你可以只計算你的ID列。

您應該從事實表中刪除status_name,因爲您應該通過鏈接到狀態維度並從那裏使用名稱列來實現。狀態名稱是來自該維度的業務密鑰,而不是非加法度量。

當您填充事實時,通常的模式是使用商業密鑰,然後從維度本身或查找表中選取代理鍵,然後僅使用代理指向尺寸的鍵。


有一個really handy Kimball guide它給出了各種技術的簡要概述。它非常方便,因爲它既是查找概念的起始位置,也是回顧您何時需要提醒的地方 - 我建議給它一個閱讀並保存它。

+1

我很無語!非常感謝你這樣詳細的回答!我會仔細研究......非常感謝你分享你的經驗!這對我來說非常重要。 –