Sql server SQL Server-仅当记录不';t已存在-需要升级流程

Sql server SQL Server-仅当记录不';t已存在-需要升级流程,sql-server,database,tsql,Sql Server,Database,Tsql,我们有一个C#程序,每晚从数千个网站获取数据,并将结果写入一个包含30列的数据库表。其中一个列(称为文本)是一个“全面”的非结构化数据列,它可以包含任何内容,从网站的一句文字到多个段落。每晚的过程产生大约200万条记录 它当前的设置是,程序将所有记录写入单独SQL Server实例中的“holding”表。然后,我们的主表(包含前一天的所有200万条记录)被完全截断。然后,保留表将所有数据发送到主表 因此,我们每天都会完全删除并重新写入所有记录。必须有一种比这更有效的方法。我想跳过看似不必要的中

我们有一个C#程序,每晚从数千个网站获取数据,并将结果写入一个包含30列的数据库表。其中一个列(称为文本)是一个“全面”的非结构化数据列,它可以包含任何内容,从网站的一句文字到多个段落。每晚的过程产生大约200万条记录

它当前的设置是,程序将所有记录写入单独SQL Server实例中的“holding”表。然后,我们的主表(包含前一天的所有200万条记录)被完全截断。然后,保留表将所有数据发送到主表

因此,我们每天都会完全删除并重新写入所有记录。必须有一种比这更有效的方法。我想跳过看似不必要的中间步骤,让程序直接写入主表。但我能想象的唯一方法是在记录不存在的情况下追加记录。这似乎令人望而生畏,因为不同记录之间的列数据极不一致(就哪些记录可能有数据,哪些记录没有数据而言),但也许我想得太多了

  • 我可以只用一张桌子来完成吗
  • 哪种最有效的方法可以确保记录只获得 考虑到记录的结构(缺少),如果它还不存在,是否编写
我已经阅读并考虑了这篇文章中的答案:但我认为答案不能满足我们的需要:它似乎只适用于一个字段上的显式WHERE子句,其值是手动指示的。

假设:

  • 同一azure数据库中有两个表
  • 暂存表已填充,名为
    stg.MyTable
    stg
    是一个架构)
  • 最后一个表是
    dbo.MyTable
  • 领域是相当相似的
以下是两种获取数据的方法:

A.截断/插入

此方法实际上使用一些CPU和磁盘来复制数据,但它保留了所有表索引、键pk等,并且不要求表完全相同

TRUNCATE TABLE dbo.MyTable

INSERT INTO dbo.MyTable (Field1, Field2, Field3)
SELECT Field1, Field2, Field3 FROM stg.MyTable

-- Optional step: clear the staging to free up space
TRUNCATE TABLE stg.MyTable
B.模式交换

这是在您的鼻子下有效旋转桌子的许多方法之一。许多不同的人似乎是孤立地提出这个问题的。它有以下限制:

  • 它要求表是相同的
  • 如果你有触发器或外键,你会非常小心
从你的描述中,我看不出有任何理由表不能完全相同

TRUNCATE TABLE dbo.MyTable

INSERT INTO dbo.MyTable (Field1, Field2, Field3)
SELECT Field1, Field2, Field3 FROM stg.MyTable

-- Optional step: clear the staging to free up space
TRUNCATE TABLE stg.MyTable
这是基于上的优秀描述(包括图表!)

简言之,你:

  • 将数据加载到stg.表中(首先清除)
  • 将活动台切换到等待区域以保留:

    alter schema holding transfer dbo.Table

  • 将staging表切换到live-您现在已经加载了数据

    alter schema dbo transfer stg.Table

  • 将表格从保留状态切换到准备接受数据的阶段

    alter schema stg transfer holding.表

  • 注意,这会破坏触发器和外键,所以需要考虑这些。

    请记住,您现在需要对这两个表进行列和索引更改。另一种选择是将索引和PK脚本保留在一旁,然后重新应用它,假设:

    • 同一azure数据库中有两个表
    • 暂存表已填充,名为
      stg.MyTable
      stg
      是一个架构)
    • 最后一个表是
      dbo.MyTable
    • 领域是相当相似的
    以下是两种获取数据的方法:

    A.截断/插入

    此方法实际上使用一些CPU和磁盘来复制数据,但它保留了所有表索引、键pk等,并且不要求表完全相同

    TRUNCATE TABLE dbo.MyTable
    
    INSERT INTO dbo.MyTable (Field1, Field2, Field3)
    SELECT Field1, Field2, Field3 FROM stg.MyTable
    
    -- Optional step: clear the staging to free up space
    TRUNCATE TABLE stg.MyTable
    
    B.模式交换

    这是在您的鼻子下有效旋转桌子的许多方法之一。许多不同的人似乎是孤立地提出这个问题的。它有以下限制:

    • 它要求表是相同的
    • 如果你有触发器或外键,你会非常小心
    从你的描述中,我看不出有任何理由表不能完全相同

    TRUNCATE TABLE dbo.MyTable
    
    INSERT INTO dbo.MyTable (Field1, Field2, Field3)
    SELECT Field1, Field2, Field3 FROM stg.MyTable
    
    -- Optional step: clear the staging to free up space
    TRUNCATE TABLE stg.MyTable
    
    这是基于上的优秀描述(包括图表!)

    简言之,你:

  • 将数据加载到stg.表中(首先清除)
  • 将活动台切换到等待区域以保留:

    alter schema holding transfer dbo.Table

  • 将staging表切换到live-您现在已经加载了数据

    alter schema dbo transfer stg.Table

  • 将表格从保留状态切换到准备接受数据的阶段

    alter schema stg transfer holding.表

  • 注意,这会破坏触发器和外键,所以需要考虑这些。

    请记住,您现在需要对这两个表进行列和索引更改。另一种选择是将索引和PK脚本保留在一旁,然后重新应用它

    两步流程(使用暂存表)实际上是个好主意。第一:您是否确实存在传输200万条记录的性能问题?因为一条SQL语句截断和加载200万条记录所需的时间应该少于10秒。如果在c#程序中逐行传输200万条记录,那么这是您的第一个问题如果您只想添加新记录,并保存截断步骤,那么只添加“新”记录的唯一方法是确定哪些是新的,唯一的方法是使用某种唯一标识记录的If标识字段。那么,数据集中的唯一标识是什么