使用自引用外键加载维度表

时间:2014-11-14 15:24:41

标签: sql-server ssis sql-server-2012 etl self-referencing-table

我正在寻找一个包含自引用键的维度表,我想了解最有效/最有效的方法。

这是我的设置:我的Staging环境中有一个Message表,其中包含两个键,Message的主键和线程中第一条消息的自引用外键。简化了表格结构,除了键取出了所有内容:

CREATE TABLE [dbo].[MsgMain](
    [MsgMain_SK] [int] IDENTITY(1,1) NOT NULL,
    [MsgMainPK1] [int] NULL,
    [ThreadPK1] [int] NULL
) ON [PRIMARY]

除了MsgMain_SK上的聚簇索引外,还有一个包含两个键的非聚簇索引:

CREATE NONCLUSTERED INDEX [IX_MsgMain] ON [dbo].[MsgMain]
(
    [MsgMainPK1] ASC,
    [ThreadPK1] ASC
)

我正在将该Message表中的数据加载到Dimension表中:

CREATE TABLE [dbo].[DimDiscussionPost](
    [DiscussionPost_SK] [bigint] IDENTITY(1,1) NOT NULL,
    [SrcDiscussionPostID] [int] NULL,
    [ThreadStarter_SK] [int] NULL
) ON [PRIMARY]

(我还没有在该表上创建索引,但我计划遵循相同的设置:集群在SK上,非集群在业务和外键上)。

我的初始加载过程如下(将转换为SSIS ETL包):

INSERT INTO [dbo].[DimDiscussionPost]
  (
    [SrcDiscussionPostID]
  )
SELECT 
    MM.MsgMainPK1 AS SrcDiscussionPostID
FROM 
    GradebookSTG9.dbo.MsgMain MM 

加载初始记录后,我返回并运行以下UPDATE语句:

UPDATE dDP
SET dDP.ThreadStarter_SK = dTS.DiscussionPost_SK
FROM 
    GradeBookSTG9.dbo.MsgMain MM 
     INNER JOIN
    MasterDM.dbo.DimDiscussionPost dDP ON 
        dDP.SrcDiscussionPostID = MM.MsgMainPK1
     INNER JOIN 
    MasterDM.dbo.DimDiscussionPost dTS ON 
        MM.ThreadPK1 = dTS.SrcDiscussionPostID 

问题一:有没有办法一步完成这两个过程?

问题二:如果我将ThreadPK1的业务密钥与MsgMainPK1一起存储在表中(即添加SrcThreadStarterID),那么更新会更有效吗?

问题三:我将其转换为SSIS(ETL)包后,我会更好:

  1. 在每行加载时将触发的触发器(我正在使用批量插入,如果重要的话)
  2. 执行SQL任务,针对所有新创建/更新的记录运行上面的UPDATE语句
  3. 将执行相同逻辑UPDATE的查找和批量更新数据流
  4. 你要提出的其他令人难以置信的巧妙建议
  5. 示例数据:

    +-----------------+-----------+
    |     MsgMainPK1  | ThreadPK1 |
    |     1234        | 1234      |
    |     1235        | 1234      |
    |     1236        | 1234      |
    |     1237        | 1234      |
    |     1238        | 1234      |
    |     1239        | 1239      |
    |     1240        | 1240      |
    |     1241        | 1240      |
    |     1242        | 1234      |
    +-----------------+-----------+
    

    所需数据:

    +-------------------+---------------------+------------------+--------------------+
    | DiscussionPost_SK | SrcDiscussionPostID | ThreadStarter_SK | SrcThreadStarterID |
    +-------------------+---------------------+------------------+--------------------+
    |                 1 |                1234 |                1 |               1234 |
    |                 2 |                1235 |                1 |               1234 |
    |                 3 |                1236 |                1 |               1234 |
    |                 4 |                1237 |                1 |               1234 |
    |                 5 |                1238 |                1 |               1234 |
    |                 6 |                1239 |                6 |               1239 |
    |                 7 |                1240 |                7 |               1240 |
    |                 8 |                1241 |                8 |               1240 |
    |                 9 |                1242 |                1 |               1234 |
    +-------------------+---------------------+------------------+--------------------+
    

1 个答案:

答案 0 :(得分:1)

你可以一次性完成。

WITH ordered_messages AS
(
  SELECT ThreadPK1, MsgMainPK1, 
    ROW_NUMBER() OVER(PARTITION BY ThreadPK1 ORDER BY MsgMainPK1) seq
  FROM MsgMain
)
INSERT INTO DimDiscussionPost(SrcDiscussionPostID, ThreadStarter_SK)
SELECT mm.MsgMainPK1, om.seq
FROM MsgMain mm
INNER JOIN ordered_messages om on om.ThreadPK1 = mm.ThreadPK1 and om.seq=1

我不完全明白你在第三个问题中的意思。您应该将数据加载到临时表中,然后将数据插入维度表中。此过程应由源数据的可用性触发,即文件已到达或SLA指定的某一时间。我不太了解您的导入过程,我不敢回答。