Как избежать ненужных обновлений при использовании в конфликте с Postgres?

#postgresql

Вопрос:

Мой вариант использования включает синхронизацию таблицы с вышестоящим источником по повторяющемуся расписанию.

Каждая строка имеет уникальный идентификатор и другие столбцы, и я хочу убедиться, что вставляю все новые восходящие строки и обновляю все измененные восходящие строки. И там могут быть тысячи строк для синхронизации.

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

В настоящее время я использую ON CONFLICT UPDATE примерно так:

 INSERT INTO symbols (id, name, status) 
VALUES 
  (1, 'one', 'online'),
  (2, 'two', 'offline'),
  ...
ON CONFLICT (id) 
UPDATE SET (id, name, status) = (excluded.id, excluded.name, excluded.status)
RETURNING *
 

Но это будет записывать обновления, даже если ничего не меняется. Как я должен настроить UPDATE , чтобы эффективно проверять и применять к строкам, которые в этом нуждаются?

Комментарии:

1. У вас возникли проблемы с производительностью? Postgres может оптимизировать обновления. Тысячи строк-это не так много.

2. @Schwern » может оптимизировать обновления » — не так ли?

Ответ №1:

Вы можете добавить предложение where, чтобы обновлять только те строки, которые отличаются.

 INSERT INTO symbols (id, name, status) 
VALUES 
  (1, 'one', 'online'),
  (2, 'two', 'offline'),
  ...
ON CONFLICT (id) DO
UPDATE SET (id, name, status) = (excluded.id, excluded.name, excluded.status)
WHERE (symbols.id, symbols.name, symbols.status) IS DISTINCT FROM (excluded.id, excluded.name, excluded.status)
RETURNING *
 

Однако это вернет только те строки, которые фактически обновлены, что может повлиять на то, как вы используете предложение returning.

Комментарии:

1. WHERE symbols IS DISTINCT FROM excluded должно сработать так же хорошо.