Какое максимальное количество скаляров можно использовать в предложении IN? - PullRequest
0 голосов
/ 05 апреля 2019

Всякий раз, когда я использую небольшое утверждение, например:

DELETE FROM c_ordertax WHERE (c_order_id,c_tax_id) IN ((183691598,1000862),(183691198,1000862));

Он выполняется отлично ... но если я выполню длинную инструкцию, чтобы удалить, скажем, 18755 записей с этими скалярными значениями, он говорит, что "max_stack_depth" превышен ... эта опция в postgresql.conf была установлена ​​в 2 МБ и запрос, который выкинул ошибку даже не до 2Мб, ее всего 300кб

Примечание: триггеры не прикреплены к таблице

И еще одна вещь, которую я заметил в отношении других запросов, это то, что когда я использую одно значение в предложении IN, например: DELETE FROM c_ordertax WHERE (c_order_id) IN ((183691598),(183691198)); у них нет проблем, и, как бы долго ни занимался запрос, он выполняется отлично ...

Мои текущие параметры:

  1. Я мог бы увеличить значение "max_stack_depth", но оно ограничено 8 МБ и его увеличение вызывает проблемы и сервер postgresql не может перезапустить ... он может только перезапустить правильно, если опция установить значение менее 8 МБ
  2. Я мог бы разделить эти заявления, но это может быть не изящно решение, и это тоже требует от меня знать максимальные скалярные значения которые могут быть размещены в одном выражении, и если количество полей увеличение скалярного значения, общее количество значений, которые могут быть боязнь, используемая в одном выражении, может уменьшить, боюсь ...

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

5 values with 2 fields => ((1,2),(1,2),(1,2),(1,2),(1,2))
2 values with 3 fields => ((1,2,3),(1,2,3))

Кто-нибудь из Database Mastermind сталкивался с подобными проблемами? Если да, то как мне справиться с этим?

Ответы [ 2 ]

2 голосов
/ 05 апреля 2019

Должно работать, если переписать список скалярных значений в список values():

DELETE FROM c_ordertax 
using (
  values 
      (183691598,1000862),
      (183691198,1000862)
) as t(ord_id,tax_id)
WHERE c_order_id = t.ord_id
  and c_tax_id = t.tax_id;

Я пробовал это с 10000 парами в списке values, и это не выдает ошибку. Это было с Postgres 11 однако. У меня сейчас нет 9.3.

1 голос
/ 05 апреля 2019

Проблема в том, что IN списки пар преобразуются следующим образом на этапе разбора:

EXPLAIN DELETE FROM large WHERE (id, id) IN ((1, 1), (2, 2), (3, 3), (4, 4), (5, 5));
                                                                      QUERY PLAN                                                                       
-------------------------------------------------------------------------------------------------------------------------------------------------------
 Delete on large  (cost=0.00..39425.00 rows=1 width=6)
   ->  Seq Scan on large  (cost=0.00..39425.00 rows=1 width=6)
         Filter: (((id = 1) AND (id = 1)) OR ((id = 2) AND (id = 2)) OR ((id = 3) AND (id = 3)) OR ((id = 4) AND (id = 4)) OR ((id = 5) AND (id = 5)))
(3 rows)

Если список состоит из скаляров, PostgreSQL может работать лучше:

EXPLAIN DELETE FROM large WHERE id IN (1, 2, 3, 4, 5);
                          QUERY PLAN                           
---------------------------------------------------------------
 Delete on large  (cost=0.00..20675.00 rows=5 width=6)
   ->  Seq Scan on large  (cost=0.00..20675.00 rows=5 width=6)
         Filter: (id = ANY ('{1,2,3,4,5}'::integer[]))
(3 rows)

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

Я не уверен, что это можно улучшить, но, вероятно, его нельзя рассматривать какдело стоит потратить много сил на.Вы всегда можете переписать свой запрос, как предложено "a_horse_with_no_name".

Обычно, если у вас длинные IN списки, подобные этому, вы, вероятно, делаете что-то неправильно, например, пытаетесь выполнить объединение вне базы данных.

...