【问题标题】:Updating Aggregated tables with new sequence使用新序列更新聚合表
【发布时间】:2018-05-24 08:06:29
【问题描述】:

一般场景:

我有一个每个用户和日期的汇总表,其中包含多个度量值。 该表最多可存储每个用户和日期 10 条记录(可能更少,具体取决于用户活动) 有一列是按日期排序的序列出现。

示例:

CREATE TABLE #Main (UserId int , DateId int , MeasureA numeric(20,2) , MeasureB numeric(20,2), PlayDaySeq int)
INSERT INTO #Main 
    VALUES (188,    20180522    ,75.00,     282287.00,  1),
           (188,    20180518    ,250.00,    1431725.00, 2),
           (188,    20180514    ,25.00,     35500.00,   3),
           (188,    20180513    ,115.00,    67100.00,   4),
           (188,    20180511    ,75.00,     10625.00,   5),
           (188,    20180510    ,40.00,     2500.00,    6),
           (188,    20180509    ,40.00,     750.00,     7),
           (188,    20180508    ,160.00,    16250.00,   8),
           (188,    20180507    ,135.00,    138200.00,  9),
           (188,    20180507    ,150.00,    68875.00,   10)

PlayDaySeq 列计算为ROW_NUMBER () OVER (PARTITION BY UserID ORDER BY DateId DESC)

这里是保存新的聚合数据的表格,这是用户:

CREATE TABLE #Inc (UserId int , DateId int , MeasureA numeric(20,2) , MeasureB numeric(20,2), PlayDaySeq int)
INSERT INTO #Inc
    VALUES (188,    20180523    ,225.00,    802921.00,  1)

现在,有一条新记录可用,所以我使用了以下内容:

INSERT INTO #Main
    SELECT * 
     FROM #Inc I
        WHERE NOT EXISTS 
            (
            SELECT 1 
            FROM #Main M
            WHERE i.UserId = M.UserId
            AND i.DateId = M.DateId
            )

问题是

我需要更新 PlayDaySeq 列,以便新记录为 1,其余记录将增加 1 并删除序列大于10的记录

最好的方法是什么? 请记住,#main 表非常大(2.5 亿条记录)。

我可以通过再次运行ROW_NUMBER 来更新序列,然后DELETE 将大于10, 我正在寻找最有效的方法。

【问题讨论】:

  • 使用像PlayDaySeq 这样的列有什么意义?使用ROW_NUMBER,如您的帖子中所述,您可以轻松地为每一行分配一个序列号。
  • 该列具有商业意义,因为我们有几个依赖于它的计算,例如从播放日期 3 到播放日期 7 之间经过了多少天。
  • 我不想过多地更新大表。
  • 首选:使用视图。第二:触发。
  • 我宁愿不使用触发器,这是一个大表,触发器会影响性能。

标签: sql-server tsql sql-server-2016


【解决方案1】:

更新一行会导致所有其他单条记录的更新听起来不是一个好主意,尽管这种情况很少见。就像已经提到的评论一样,我认为不需要这样的专栏。 但你说你有你的理由,所以我会假设这是真的。

我的建议是将 PlayDaySeq 放在桌面上并创建一个视图,其中包含以下内容作为附加列。

ROW_NUMBER () OVER (PARTITION BY UserID ORDER BY DateId DESC) AS PlayDaySeq

然后,无论您的代码现在使用该表什么,都应该使用视图,应该保持最小的更改。但是您需要对此进行测试,看看性能如何。此外,如果您将视图更改为索引视图,SQL Server 会将值存储为类似表的内容,当您插入新记录时,它会自动为您更新内容,您再次需要在插入时测试性能。

如果我是你,我会更愿意尝试不同的方法,例如我将其设置为 100,200,300,而不是设置为 1,2,3,因此当插入需求较小时,例如每天 20 条记录,我就不需要更新休息记录,但只输入 11,12 101,102 仍然可以保持顺序正确,并且夜间工作将整个表更新为 100,200,300 以便第二天重新开始,或者使代码仅在用完时才执行数字, ,但由于您在陈述其他含义时使用它的方式,它可能根本不起作用。

【讨论】:

  • 我会尝试使用视图,我需要对性能进行一些测试,因为查询表 + 额外计算 ROW_NUMBER 可能非常“繁重”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-10-26
  • 1970-01-01
  • 2015-06-24
  • 1970-01-01
  • 1970-01-01
  • 2016-06-26
相关资源
最近更新 更多