Синхронизация двух таблиц с использованием хранимой процедуры, только обновление и добавление строк, где значения не совпадают - PullRequest
2 голосов
/ 16 февраля 2012

Сценарий

У меня есть две таблицы с одинаковой структурой.

TABLE [INFORMATION], [SYNC_INFORMATION]

    [ITEM] [nvarchar](255) NOT NULL
    [DESCRIPTION] [nvarchar](255) NULL
    [EXTRA] [nvarchar](255) NULL
    [UNIT] [nvarchar](2) NULL
    [COST] [float] NULL
    [STOCK] [nvarchar](1) NULL
    [CURRENCY] [nvarchar](255) NULL
    [LASTUPDATE] [nvarchar](50) NULL
    [IN] [nvarchar](4) NULL
    [CLIENT] [nvarchar](255) NULL

Я пытаюсь создать процедуру синхронизации, которая будет запускаться запланированным событием в определенное время каждый день.

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 строк, когда, возможно, это нужно только 20.

Можно ли сделать это лучше илиоптимизирован?
Нужны ли улучшения, если да, где?

Как бы вы решили это?

Также был бы признателен за некоторые различия во времени между решениями, чтобы я мог их сравнить.

ОБНОВЛЕНИЕ

Использование marc_s CHECKSUM действительно блестяще.Проблема в том, что в некоторых случаях информация создает одну и ту же контрольную сумму.Вот пример, из-за секретного контента, я могу показать вам только 2 столбца, но могу сказать, что все столбцы имеют одинаковую информацию, кроме этих 2. Для пояснения: на этом снимке экрана показаны все строки, которые имели дубликаты CHECKSUM s.Это также единственные строки с дефисом в столбце ITEM, которые я посмотрел.

enter image description here

Запрос был просто

SELECT *, CHECKSUM(*) FROM SYNC_INFORMATION

1 Ответ

2 голосов
/ 16 февраля 2012

Если вы можете немного изменить структуру таблицы - вы можете добавить вычисляемый столбец CHECKSUM к вашим двум таблицам, и в случае, если ITEM идентичен, вы можете проверить этот столбец контрольной суммы, чтобы увидеть, есть ли есть ли какие-либо различия в столбцах таблицы.

Если вы можете сделать это - попробуйте что-то вроде этого здесь:

ALTER TABLE dbo.[INFORMATION]
  ADD CheckSumColumn AS CHECKSUM([DESCRIPTION], [EXTRA], [UNIT],
                                 [COST], [STOCK], [CURRENCY],
                                 [LASTUPDATE], [IN], [CLIENT]) PERSISTED

Конечно: включайте только те столбцы, которые следует учитывать при проверке идентичности исходной и целевой строк! (это зависит от ваших потребностей и требований)

Это сохраняет новый столбец в вашей таблице, который вычисляется как контрольная сумма для столбцов, указанных в списке аргументов функции CHECKSUM.

Это значение сохраняется, т. Е. Оно также может быть проиндексировано! : -О

Теперь вы можете упростить ваш UPDATE до

 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

Подробнее о функции CHECKSUM T-SQL в MSDN !

...