Допустим, у нас есть следующая таблица:
create table states (
id serial primary key,
info varchar(64)
nodes integer ARRAY
);
create index states_nodes on states using gin(nodes);
И Node.js используется для связи с базой данных.
С инвариантом, что if nodes
обновляется правильно, у него не будет повторяющихся значений, как этого добиться?
предположим, что текущее значение nodes
равно A
, а массив, который мы хотим добавить к nodes
, равен B
. Я придумал два подхода:
- написать запрос, чтобы получить
A ⋃ (B - A)
и использовать его напрямую update states set nodes = (select ...) where id=?
- написать запрос, чтобы получить
B - A
и создать новый запрос: update states set nodes = array_concat(nodes, ?::integer[]) where id=?
и заполните его результатом первого.
Итак, основные вопросы?
- каковы компромиссы этих двух? Или есть другой способ?
- какой подход наиболее эффективен и как написать его запрос?
Мои попытки
Подход 2:
select array(
select unnest(?::integer[])
except
select unnest(nodes) from states where id=?
);
Подход 1:
update states
set
nodes = (select array_agg(distinct elem)
from states, unnest(array_cat(nodes, ?::integer[])) elem
where id = ?)
where id=?;
второй занимает разное время (от 0,500 мс до 400 мс при использовании анализа объяснения)! Может быть, из-за индекса GIN?