Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 使用存储过程同步两个表,仅更新和添加值不匹配的行 场景_Performance_Sql Server 2005_Tsql_Stored Procedures - Fatal编程技术网

Performance 使用存储过程同步两个表,仅更新和添加值不匹配的行 场景

Performance 使用存储过程同步两个表,仅更新和添加值不匹配的行 场景,performance,sql-server-2005,tsql,stored-procedures,Performance,Sql Server 2005,Tsql,Stored Procedures,我有两张结构相同的桌子 表[信息],[同步信息] [项目][nvarchar](255)不为空 [说明][nvarchar](255)空 [EXTRA][nvarchar](255)空 [单位][nvarchar](2)空 [成本][浮动]空 [股票][nvarchar](1)空 [货币][nvarchar](255)空 [LASTUPDATE][nvarchar](50)空 [IN][nvarchar](4)空 [CLIENT][nvarchar](255)空 我正在尝试创建一个同步过程,该

我有两张结构相同的桌子

表[信息],[同步信息]
[项目][nvarchar](255)不为空
[说明][nvarchar](255)空
[EXTRA][nvarchar](255)空
[单位][nvarchar](2)空
[成本][浮动]空
[股票][nvarchar](1)空
[货币][nvarchar](255)空
[LASTUPDATE][nvarchar](50)空
[IN][nvarchar](4)空
[CLIENT][nvarchar](255)空
我正在尝试创建一个同步过程,该过程将在每天给定的时间由计划事件触发

CREATE PROCEDURE [dbo].[usp_SynchronizeInformation]
AS
BEGIN
    SET NOCOUNT ON;

    --Update all rows
    UPDATE TARGET_TABLE
    SET TARGET_TABLE.[DESCRIPTION] = SOURCE_TABLE.[DESCRIPTION],
        TARGET_TABLE.[EXTRA] = SOURCE_TABLE.[EXTRA],
        TARGET_TABLE.[UNIT] = SOURCE_TABLE.[UNIT],
        TARGET_TABLE.[COST] = SOURCE_TABLE.[COST],
        TARGET_TABLE.[STOCK] = SOURCE_TABLE.[STOCK],
        TARGET_TABLE.[CURRENCY] = SOURCE_TABLE.[CURRENCY],
        TARGET_TABLE.[LASTUPDATE] = SOURCE_TABLE.[LASTUPDATE],
        TARGET_TABLE.[IN] = SOURCE_TABLE.[IN],
        TARGET_TABLE.[CLIENT] = SOURCE_TABLE.[CLIENT]
    FROM SYNC_INFORMATION TARGET_TABLE 
        JOIN LSERVER.dbo.INFORMATION SOURCE_TABLE ON TARGET_TABLE.ITEMNO = SOURCE_TABLE.ITEMNO
    WHERE TARGET_TABLE.ITEMNO = SOURCE_TABLE.ITEMNO

    --Add new rows
    INSERT INTO SYNC_INFORMATION (ITEMNO, DESCRIPTION, EXTRA, UNIT, STANDARDCOST, STOCKTYPE, CURRENCY_ID, LASTSTANDARDUPDATE, IN_ID, CLIENTCODE)
    SELECT 
        src.ITEM, 
        src.DESCRIPTION,
        src.EXTRA,
        src.UNIT,
        src.COST,
        src.STOCKTYPE,
        src.CURRENCY_ID,
        src.LASTUPDATE,
        src.IN,
        src.CLIENT
    FROM LSERVER.dbo.INFORMATION src
        LEFT JOIN SYNC_INFORMATION targ ON src.ITEMNO = targ.ITEMNO
    WHERE
        targ.ITEMNO IS NULL
END
目前,执行此过程(包括同时执行的其他一些过程)大约需要15秒。 我计划在我的工作界面中添加一个“同步”按钮,以便用户可以在添加新项目并需要在同一天使用时手动同步

但为了让我做到这一点,我需要尽可能缩短这15秒


不必像在我的过程中那样更新每一行,是否可以只更新值不匹配的行?
这将大大提高执行速度,因为它不必在实际需要时更新所有4000行

这能以更好的方式完成吗,或者优化吗?
是否需要改进,如果需要,在哪里

你将如何解决这个问题

我也希望解决方案之间有一些时间上的差异,这样我可以比较它们

更新 使用marc_的校验和(CHECKSUM)真是太棒了。问题是,在某些情况下,信息会创建相同的校验和。这里有一个例子,由于分类内容,我只能向您显示两列,但我可以说,除了这两列之外,所有列都有相同的信息。澄清:此屏幕截图是具有重复的
校验和的所有行的屏幕截图。在
ITEM
列中,这些也是唯一一个带有连字符的行

这个问题很简单

SELECT *, CHECKSUM(*) FROM SYNC_INFORMATION

如果可以稍微更改表结构,则可以在两个表中添加一个计算的
校验和
列,如果
相同,则可以检查该校验和列,以查看表中的列是否存在任何差异

如果您能做到这一点,请尝试以下方法:

ALTER TABLE dbo.[INFORMATION]
  ADD CheckSumColumn AS CHECKSUM([DESCRIPTION], [EXTRA], [UNIT],
                                 [COST], [STOCK], [CURRENCY],
                                 [LASTUPDATE], [IN], [CLIENT]) PERSISTED
当然:只包括在确定源行和目标行是否相同时应考虑的列!(这取决于您的需要和要求)

这将在表中保留一个新列,该列作为
checksum
函数的参数列表中指定的列的校验和进行计算

此值被持久化,即它也可以被索引!:-O

现在,您可以将
更新简化为

 UPDATE TARGET_TABLE
 SET ......
 FROM SYNC_INFORMATION TARGET_TABLE 
 JOIN LSERVER.dbo.INFORMATION SOURCE_TABLE ON TARGET_TABLE.ITEMNO = SOURCE_TABLE.ITEMNO
 WHERE 
     TARGET_TABLE.ITEMNO = SOURCE_TABLE.ITEMNO
     AND TARGET_TABLE.CheckSumColumn <> SOURCE_TABLE.CheckSumColumn
更新目标表
设置
从同步信息目标表
在目标_TABLE.ITEMNO=源_TABLE.ITEMNO上加入LSERVER.dbo.INFORMATION SOURCE_TABLE
哪里
目标_TABLE.ITEMNO=源_TABLE.ITEMNO
和目标_TABLE.CheckSumColumn源_TABLE.CheckSumColumn

了解更多有关该网站的信息

您正在使用哪个版本的SQL Server??SQL Server 2008有一个新的
MERGE
命令,正是针对这种情况……@Fosco应该提到其中一个表位于另一个非常繁忙的服务器上,我只有读取权限。我正在使用这些数据在我的界面中进行一些计算,因此为了减轻工作量,我将数据传输到另一台服务器,并仅在需要时进行同步。@marc_两台服务器都是2005年的。当前,聚集索引与主键相同,
ITEMNO
。到目前为止没有其他索引。我无法在您的表结构中看到
ITEMNO
。。。。。。这是什么样的专栏?噢,对不起,我改了名字。我会修好的
ITEMNO
ITEM
,它是一个
nvarchar
。我在其中一条评论中写道,我只对其中一台服务器具有读取权限。因此,我不能添加任何列:/然而,我必须说,这是一个出色的解决方案。它就像一个自定义哈希索引,对每行合并的所有列进行索引!是否可以执行
TARGET_TABLE.CHECKSUM列校验和(column1、column2、column3、column4…)
,并且不占用太多计算?因为这将是一个非常好的解决方案。@ShadowScripter:是的,如果您不能更改源表,您可以让它在
SELECT
语句中计算
CHECKSUM
。虽然没有将其持久化到表中那样有效,但仍然希望它是一个相当好的指标,表明是否有什么改变!不起作用,实际上它几乎起作用了,但是有7行计算了相同的校验和。这些行几乎相同,其中一行有4英寸
和6英寸
说明
,另一行有6英寸
和4英寸
说明
,这导致了相同的校验和。@ShadowScripter您是否对列的子集应用了校验和?我无法获取
INT
s或
VARCHAR
s来为(
4
6
)的所有组合生成相同的
CHECKSUM()
值。您能否显示导致此冲突的实际行和
CHECKSUM()
计算?@AaronBertrand一些信息是保密的,但我会尽可能多地向您显示。