1

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

这是我的设置:我的暂存环境中有一个 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的业务key和MsgMainPK1一起存入表中(即添加SrcThreadStarterID),更新效率会不会更高?

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

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

样本数据:

+-----------------+-----------+
|     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 |
+-------------------+---------------------+------------------+--------------------+
4

1 回答 1

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 指定的一天中的特定时间。恐怕我对您的进口流程了解得不够多,无法回答这个问题。

于 2014-11-15T08:05:55.433 回答