Как эффективно проверить, содержит ли база данных запись, идентичную ожидающей вставке? - PullRequest
2 голосов
/ 15 февраля 2012

У меня есть некоторые записи, которые я хочу «вставить или обновить» в базе данных SQL Server с помощью хранимой процедуры. Эти записи имеют глобально уникальный и стабильный идентификатор и набор атрибутов значений (около десятка).

Проверка на вставку достаточно проста - посмотрите, не существует ли ключ в таблице.

Предполагая, что ключ существует, мне нужно проверить, содержит ли существующая запись точно те же значения, что и текущие данные, которые я передаю в процедуру. На данный момент я делаю это через:

SELECT @identical = CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END FROM Table
    WHERE idCol = @newId
      AND valueCol1 = @newValue1
      AND valueCol2 = @newValue2
      AND ...

Это работает, но не очень эффективно; Я могу вставлять около 70 записей в секунду, что намного медленнее, чем я ожидал.

Моей первой мыслью было добавить индекс - но он будет индексировать почти каждый столбец в таблице. Будет ли это иметь смысл или это будет просто вторая копия таблицы? (Столбец ID является кластеризованным PK, если это актуально.)

Есть ли какой-нибудь разумный способ ускорить запрос, который должен проверять значения каждого столбца? Я рассматриваю возможность использования некоторого вида хэша для обнаружения дубликатов, но это добавляет некоторый объем служебной информации, усложняет sprocs и малую (приемлемую) вероятность ложных срабатываний, поэтому я бы предпочел решение на основе индексов или переписать SQL, если один существует.

Ответы [ 3 ]

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

Вы можете использовать инструкцию MERGE, если вы используете SQL Server 2008

1 голос
/ 15 февраля 2012

Не тестируйте заранее, просто позвольте выражениям where сделать всю работу за вас.псевдокод (ваш синтаксис может отличаться)

UPDATE thetable
   SET valueCol1 = @newValue1
     , valueCol2 = @newValue2
     , ...
WHERE idCol = @newId
  AND (valueCol1 <> @newValue1
      OR valueCol2 <> @newValue2
      OR ...
      );

IF (ROWCOUNT > 0) RETURN;

INSERT INTO thetable (idCol, valueCol1, valueCol2, ...)
VALUES (@newId, @newValue1,  @newValue2, ... )
WHERE NOT EXISTS ( SELECT * FROM thetable nx
    WHERE nx.idCol = @newId
    );
0 голосов
/ 15 февраля 2012

Вот классическое решение

if exists (select * from thetable where idCol = @newID)
begin
    update ....
end
else
begin
   insert ...
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...