2015-12-28 2 views
2

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

Это лучшее решение я нашел для текущей версии Postgres (9.4): http://www.depesz.com/2012/06/10/why-is-upsert-so-complicated/ http://www.postgresql.org/docs/current/static/plpgsql-control-structures.html#PLPGSQL-UPSERT-EXAMPLE

Как правило, предложенное решение основано на алгоритме: вставить одну строку, если произошло ошибка - делать что-то, если нет - вставьте следующий.

Если все, что мне нужно, это игнорировать повторяющиеся ошибки, могу ли я просто сделать это?

INSERT INTO tablename (id,name,surname) values (1,'john','doe') 
INSERT INTO tablename (id,name,surname) values (2,'jane','smith') 

вместо этого:

INSERT INTO tablename (id,name,surname) values (1,'john','doe'),(2,'jane','smith') 

... если я должен вставить только ~ 5-30 строк за один раз? поэтому некоторые вставленные строки просто возвращают повторяющиеся ошибки, но остальные из них будут выполнены успешно. На самом деле это все, что мне нужно.

Я попытался сравнить стоимость этих подходов на EXPLAIN INSERT 100 строк сразу и 100 строк отдельно. Возможно, что я делаю что-то неправильно, потому что это показывает ~ 25-50 раз меньше времени выполнения, когда я вставка строк отдельно, как и в первом примере:

INSERT INTO tablename (id,name,surname) values (1,'john','doe') 
INSERT INTO tablename (id,name,surname) values (2,'jane','smith') 

Вот обертка запрос я использую :

BEGIN; 
EXPLAIN ANALYZE 
-- query or queriES here 
ROLLBACK; 

Итак, вопрос в том, почему я получаю это? Может быть, EXPLAIN показывает время выполнения для каждой строки, а не всего запроса? Тогда это имеет смысл: в этом случае объемная вставка будет стоить ~ 3 раза меньше, чем разделенные команды. Правильно?

+0

Если вы выбрали _not_, чтобы перейти с объемной вставкой, ваша бизнес-логика подготовлена ​​для обработки ситуации, когда, скажем, половина ваших записей была вставлена, а другая половина не была? –

+0

совершенно! если он не сделает время выполнения запроса, скажем, в 50 раз дольше, тогда отдельная вставка именно то, что мне нужно – stkvtflw

+0

. Итак, вы говорите, что время выполнения занимало в 25-50 раз меньше, например, 100 вставок отдельно или 100 навалом? –

ответ

1
with i (id, name, surname) as (values (1,'john','doe'),(2,'jane','smith')) 
insert into t (id, name, surname) 
select id, name, surname 
from i 
where not exists (
    select 1 
    from t 
    where id = i.id and name = i.name and surname = i.surname 
) 

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

+0

, вы предлагаете сделать еще два выбора для каждой вставки. Я почти уверен, что это стоит гораздо больше, чем просто вставки без выбора). – stkvtflw

+1

@stkvtflw: «еще два варианта для каждой вставки»: вы ошибаетесь, вышеупомянутый запрос - это фактически один оператор и, вероятно, самый эффективный. (BTW: нет необходимости заботиться об эффективности при вставке только нескольких строк) – joop

Смежные вопросы