powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Оптимизация INSERT-ов
25 сообщений из 43, страница 1 из 2
Оптимизация INSERT-ов
    #39932554
JDS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть таблица с парой индексов.
В нее идет интенсивная вставка в среднем по 20 записей за раз (в ХП передается массив и потом Insert из select from unnset(array)).

Если индексы убрать, то 2млн записей вставляются за 25сек (на рабочей машине, не сервер).
С индексами - 40сек.
Разница ощутимая, но индексы нужны.

Вопрос. Как можно ускорить?

Есть ли в Postgre IOT? (нашел только CLUSTER, но так понимаю, что в БД будет все равно два объекта индекс и таблица и в общем скорость вставки в CLUSTER-ed table получается такая же, как и в варианте таблица + индексы).
Есть ли в Postgre хинты? (что-нибудь типа append)
...
Рейтинг: 0 / 0
Оптимизация INSERT-ов
    #39932576
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
JDS
Есть таблица с парой индексов.
В нее идет интенсивная вставка в среднем по 20 записей за раз (в ХП передается массив и потом Insert из select from unnset(array)).

Если индексы убрать, то 2млн записей вставляются за 25сек (на рабочей машине, не сервер).
С индексами - 40сек.
Разница ощутимая, но индексы нужны.

Вопрос. Как можно ускорить?

Есть ли в Postgre IOT? (нашел только CLUSTER, но так понимаю, что в БД будет все равно два объекта индекс и таблица и в общем скорость вставки в CLUSTER-ed table получается такая же, как и в варианте таблица + индексы).
Есть ли в Postgre хинты? (что-нибудь типа append)


Это нормальный overhead на работу с индексами. Ничего с этим сделать не получится.

А вот как ускорить уже вопрос интереснее.
Попробуйте замерять время вставки тех же 2М записей через COPY FROM FILE предназначеном для батч операций (без хранимок, insert и прочего).
Тогда будет понянее предельная скорость достижимая на вашей конкретной рабочей машине и на конкретной настройке базы.
После чего можно будет думать о параметрах железа, настройке базы и тд (там тоже легко 2-3 раза скорости выйграть можно).
...
Рейтинг: 0 / 0
Оптимизация INSERT-ов
    #39932601
JDS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk , сравнил.
Insert 2млн записей
Наличие индексовInsert по 20 записей (сек)Insert по 200 записей (сек)Copy from fileС индексами552525Без индексов301817

В итоге получается, если программно вставлять не по 20, а по 200 записей, то получается чуть ли не быстрее чем copy from file (тк в программном варианте еще идет вставка в мастер-таблицу, генерация сиквенса и case-ы в каждом поле таблицы деталей, куда заливаем 2млн записей, а время то же самое).

То есть сам механизм работает так же по скорости, если брать пакеты большего размера.
Но засада в том, что вставлять надо все же по 20 записей, а чаще еще меньше - например по 10.

Может есть возможность распараллелить?
То есть разбить таблицу на патиции по хешу например или другие варианты и грузить параллельно.
В постгре это шардинг называется?
Можно ли при шардинге таблицу держать в одной БД, а ее патиции разнести на разные диски?
Или шардинг это когда таблицу кладут в разные ноды кластера?
При шардинге не поддерживаются глобальные уник индексы?
Надеюсь, что просто не умею готовить, но пока грустно со скоростями.
Попробую еще на машине с SSD.
...
Рейтинг: 0 / 0
Оптимизация INSERT-ов
    #39932603
JDS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Попробовал еще так
1. делаем копию таблицы с 2млн записей (кстати ctas - 7сек вот это нормальная скорость :)
2. truncate исх таблицы
3. insert select в исх таблицу с индексами 30сек, без индексов - те же 18сек
...
Рейтинг: 0 / 0
Оптимизация INSERT-ов
    #39932607
JDS
Но засада в том, что вставлять надо все же по 20 записей, а чаще еще меньше - например по 10.

по 10 записей 200000 раз надо вставить?
лучше буферизуйте их тогда
...
Рейтинг: 0 / 0
Оптимизация INSERT-ов
    #39932622
Swa111
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
JDS,

А если использовать такой вариант: создать копию таблицы без индексов, вставлять в нее данные, как только счетчик доходит допустим до 200, делать инсерт из нее в основную таблицу, truncate и сброс секвенса в 0.
...
Рейтинг: 0 / 0
Оптимизация INSERT-ов
    #39932661
JDS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Swa111 , суть как предложил Алексей, но так будет дольше (инсерт в таблицу без индексов уже время то же самое, потом еще + переливка в таблицу с индексами).

Алексей Роза , да, хороший вариант по-моему.
Но возникают другие моменты (особенно 3):
1. Сиквенс придется генерить на стороне приложения (это конечно решаемо, не вопрос)
2. Если приложение падает, то накрываются все данные в буфере, но по бизнесу этим можно пожертвовать.
3. Сейчас в процедуру передается массив целых чисел (ID-шников) и кучка параметров, на основе которых генерятся значения для других полей в таблице через case-ы в самом запросе.
Если сначала буферизовать данные, для набора пакета большего объема, то придется передавать не просто массив целых чисел, а уже желательно массив записей, то есть объектов.
Поэтому вопрос, есть ли возможность в Postgres передавать из Java CallableStatement набор объектов (так-то в CallableStatement есть метод setObject, это поищу что за зверь).
Либо передавать массив строк с json, а в постгре json_to_recordset, но не охота парсить ибо тоже затраты времени.
...
Рейтинг: 0 / 0
Оптимизация INSERT-ов
    #39932672
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
JDS

В итоге получается, если программно вставлять не по 20, а по 200 записей, то получается чуть ли не быстрее чем copy from file (тк в программном варианте еще идет вставка в мастер-таблицу, генерация сиквенса и case-ы в каждом поле таблицы деталей, куда заливаем 2млн записей, а время то же самое).

То есть сам механизм работает так же по скорости, если брать пакеты большего размера.
Но засада в том, что вставлять надо все же по 20 записей, а чаще еще меньше - например по 10.



Тут я сильно подозреваю что вы в свое железо и настройки базы упираетесь.
Что у вас стоит в
synchronous_commit
max_wal_size
checkpoint_timeout
shared_buffers

возможно загрузка у вас в fsync данных на диск упирается (и тогда понятно почему большие батчи идут быстрее).

ps: а зачем вам партиции и шардирование для паралельной загрузки то? пишите спокойно в таблицу в 10 потоков и будет вам быстрее (насколько - зависит от вашего оборудования).
...
Рейтинг: 0 / 0
Оптимизация INSERT-ов
    #39932682
JDS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk , итак пишу через тредпул в 15 потоков, это конечно дает ощутимый прирост, но диск-то все равно один.

Памяти на машине 8GB, параметры:
synchronous_commit - on
max_wal_size - 1GB
checkpoint_timeout - 5min
shared_buffers - 128MB
...
Рейтинг: 0 / 0
Оптимизация INSERT-ов
    #39932689
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
JDS
Maxim Boguk , итак пишу через тредпул в 15 потоков, это конечно дает ощутимый прирост, но диск-то все равно один.

Памяти на машине 8GB, параметры:
synchronous_commit - on
max_wal_size - 1GB
checkpoint_timeout - 5min
shared_buffers - 128MB


Протестируйте с
synchronous_commit =off
max_wal_size=16GB
checkpoint_timeout=60min
shared_buffers=2GB

только рестарт базы не забудьте сделать после изменений (скорее всего влиять будет первый и последний параметр в основном).
...
Рейтинг: 0 / 0
Оптимизация INSERT-ов
    #39932697
JDS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk , попробовал.
Да получается побыстрее.
Немного нелинейная зависимость получается, но и зависимость от размера пакета сохраняется, то есть вариант с буферизацией на стороне приложения пока актуален.
Да и изменение параметров возможно влечет другие риски в частности настораживает
synchronous_commit =off.

Вставка 2млн записей
Наличие индексовПакетами по 20 записей (сек)Пакетами по 200 записей (сек)Без индексов2620 С индексами3630

При этом в варианте без индексов по 200 записей время загрузки стало сильно нестабильным и колеблется от 11 до 35 секунд.
...
Рейтинг: 0 / 0
Оптимизация INSERT-ов
    #39932698
JDS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
deleted
...
Рейтинг: 0 / 0
Оптимизация INSERT-ов
    #39932711
JDS
Swa111 , суть как предложил Алексей, но так будет дольше (инсерт в таблицу без индексов уже время то же самое, потом еще + переливка в таблицу с индексами).

Алексей Роза , да, хороший вариант по-моему.
Но возникают другие моменты (особенно 3):
1. Сиквенс придется генерить на стороне приложения (это конечно решаемо, не вопрос)
2. Если приложение падает, то накрываются все данные в буфере, но по бизнесу этим можно пожертвовать.
3. Сейчас в процедуру передается массив целых чисел (ID-шников) и кучка параметров, на основе которых генерятся значения для других полей в таблице через case-ы в самом запросе.
Если сначала буферизовать данные, для набора пакета большего объема, то придется передавать не просто массив целых чисел, а уже желательно массив записей, то есть объектов.
Поэтому вопрос, есть ли возможность в Postgres передавать из Java CallableStatement набор объектов (так-то в CallableStatement есть метод setObject, это поищу что за зверь).
Либо передавать массив строк с json, а в постгре json_to_recordset, но не охота парсить ибо тоже затраты времени.

под буферизацией имеется ввиду складывание строк в файл под будущий COPY
а когда их набралось 2 млн (ну или пачками по 50000 грузите хотя бы - от этого тоже скорость зависит), то разом их все загрузили в БД
и никаких потерь нет.
...
Рейтинг: 0 / 0
Оптимизация INSERT-ов
    #39932712
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
JDS
Maxim Boguk , попробовал.
Да получается побыстрее.
Немного нелинейная зависимость получается, но и зависимость от размера пакета сохраняется, то есть вариант с буферизацией на стороне приложения пока актуален.
Да и изменение параметров возможно влечет другие риски в частности настораживает
synchronous_commit =off.

Вставка 2млн записей
Наличие индексовПакетами по 20 записей (сек)Пакетами по 200 записей (сек)Без индексов2620 С индексами3630


При этом в варианте без индексов по 200 записей время загрузки стало сильно нестабильным и колеблется от 11 до 35 секунд.\

значит у вас упирается все в скорость fsync на вашем диске... на механике вообще больше 200-300 коммитов в секунду делать не получается по честному... поэтому вот так и работает.
Будут быстрые ssd - разница между synchronous_commit =off и on будет не такой ощутимой (ну или нормальный рейд с кешом и батарейкой исправной на механических дисках).
...
Рейтинг: 0 / 0
Оптимизация INSERT-ов
    #39932719
JDS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей Роза , тоже так думал, но во-первых, буде не сильно быстрее (в файл же тоже надо записать), во-вторых, самое главное, к этим данным могут идти селекты, а из файла не поселектишь особо ), поэтому придется все равно на время пока данные не легли в БД держать их в памяти, то есть буфер на 200+- записей
Maxim Boguk , ок, попробую на SSD еще.
И еще все же интересно что там с шардингом )
...
Рейтинг: 0 / 0
Оптимизация INSERT-ов
    #39932721
JDS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хотя селектить данные, которые еще не легли в БД тоже негуд, т.к. юзер заселектил из буфера приложения, дальше приложение вдруг упало и после восстановления пользователь уже не увидит данные, которые он видел до падения ибо они не записались в базу из буфера.
...
Рейтинг: 0 / 0
Оптимизация INSERT-ов
    #39932757
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
JDS
Алексей Роза , тоже так думал, но во-первых, буде не сильно быстрее (в файл же тоже надо записать), во-вторых, самое главное, к этим данным могут идти селекты, а из файла не поселектишь особо ), поэтому придется все равно на время пока данные не легли в БД держать их в памяти, то есть буфер на 200+- записей
Maxim Boguk , ок, попробую на SSD еще.
И еще все же интересно что там с шардингом )


у вас на том оборудовании что есть упирается не в запись в датафайлы а в запись в wal лог (fsync точнее) а он один и пишется последовательно
(судя по вашим результатам) и всегда на одно устройство
так что от шардинга ему ни холодно не жалко
зато есть польза от выноса wal лога на другое/отдельное физическое устройство.
В общем это больше к администрированию базы а не к архитектуре приложения вопрос.


>>Может есть возможность распараллелить?
>>То есть разбить таблицу на патиции по хешу например или другие варианты и грузить параллельно.
>>В постгре это шардинг называется?
это именно партиционирование называется... шардинг - когда на много независимых серверов с базами данных раскидывается нагрузка
только пользы от него тут вам будет мало (не там узкое место).

Можно ли при шардинге таблицу держать в одной БД, а ее патиции разнести на разные диски?
Да

Или шардинг это когда таблицу кладут в разные ноды кластера?
Да.

При шардинге не поддерживаются глобальные уник индексы?
В зависимости от версии... в старых версиях вообще нет... в новых "Unique constraints on partitioned tables must include all the partition key columns. This limitation exists because PostgreSQL can only enforce uniqueness in each partition individually." что по сути тоже нет )).
...
Рейтинг: 0 / 0
Оптимизация INSERT-ов
    #39932770
JDS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk , спасибо за пояснения.
Попутно еще возник вопрос по деградации производительности с ростом объема.
То есть.
2млн записей вставляются в среднем за 25сек (условно 80тыс. записей/сек)
А 30млн записей - за 22.5 минуты (примерно 22тыс записей/сек)
То есть с ростом объема скорость падает практически в 4 раза в данном случае, что довольно ощутимо.
Как боремся с этим?

И все-таки шардинг и патиционирование - разные вещи значит?
То есть таблица может быть и патиционирована и шардирована одновременно.
В общем надо еще курить документацию, хотя бы основы, то тут все немного по-другому похоже )
...
Рейтинг: 0 / 0
Оптимизация INSERT-ов
    #39932832
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
JDS
Maxim Boguk , спасибо за пояснения.
Попутно еще возник вопрос по деградации производительности с ростом объема.
То есть.
2млн записей вставляются в среднем за 25сек (условно 80тыс. записей/сек)
А 30млн записей - за 22.5 минуты (примерно 22тыс записей/сек)
То есть с ростом объема скорость падает практически в 4 раза в данном случае, что довольно ощутимо.
Как боремся с этим?


Скорее всего данные перестают помещаться в кеш OS и shared buffer базы и начинают с диска читаться - и борятся с этим более быстрыми дисками (в пределе intel optane) или наращиванием памяти на сервере.
Ну и checkpoints начинаются которые уже нагруженный диск - совсем ушатывают.
Вообще бессмысленно проводить тесты производительности не на том оборудовании на котором проект планируется к работе.




И все-таки шардинг и патиционирование - разные вещи значит?
То есть таблица может быть и патиционирована и шардирована одновременно.

Да может быть и так... но только шардирование это уже задача приложения а не базы (т.е. штатных методов шардирования в postgresql нет это всегда что то самописное).
...
Рейтинг: 0 / 0
Оптимизация INSERT-ов
    #39933394
JDS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk, спасибо, теперь с шардингом еще понятнее, думал, это в коробке)

Продолжаю эксперименты.
Пока самый быстрый вариант это передача массива и select from unnest пакетами в районе 200 значений в массиве.

Но ввиду обьединения многих вызовов по 10-20 записей в один через буфер на 200 записей, нужен многомерный массив или обьекты типа pojo(это не пробовал, не знаю есть ли это в постгре).

Поэтому.
Пробовал еще просто батч инсерты - unnest быстрее.
Пробовал засунуть все 200 записей в json и потом select from json_to_recordset - unnest быстрее.

Пробовал передавать в процедуру в каждый из параметров отдельный массив и массив индексов массива - мало того, что криво но unnest из одного массива все равно ощутимо быстрее.

Можно было бы попробовать передавать массив строк с разделителями и потом их парсить, но думаю, это будет примерно как с json_torecordset.

Есть другая мысль. Передаются только числа. То есть можно пофиксить формат, выделив для каждого параметра определенное кол-во байт. И тогда парсить можно будет быстрее, сразу задавая смещение. Поэтому вопрос есть ли в постгре возможность работы с бинарными данными?
То есть передавать одномерный массив, элементы которого двоичные данные. Хотя потом их все равно придется приводить к тому же bigint например.
...
Рейтинг: 0 / 0
Оптимизация INSERT-ов
    #39933587
JDS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
CREATE OR REPLACE FUNCTION TEST_INSERT(P_PARAM text[]) RETURNS BIGINT AS $$
DECLARE
   id  BIGINT  := NULL;
BEGIN
   INSERT INTO trst_results(filed1, filed2, filed3, filed4, filed5) 
   SELECT SUBSTRING(UNNEST FROM 1 FOR 10)::bigint, 
          SUBSTRING(UNNEST FROM 12 FOR 10)::bigint,
          SUBSTRING(UNNEST FROM 23 FOR 2)::float,
          SUBSTRING(UNNEST FROM 26 FOR 2)::float, 
          SUBSTRING(UNNEST FROM 29 FOR 2)::float
     FROM UNNEST(P_PARAM);

   RETURN id;
END
$$ LANGUAGE 'plpgsql';


Попробовал просто массив строк с фиксированным форматом. По скорости так же как вставка пакетами по 20 строк. То есть медленне чем json_to_recordset.
Но может криво написано с типами и преобразованием.
...
Рейтинг: 0 / 0
Оптимизация INSERT-ов
    #39933597
JDS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сделал таблицу с со всеми чаровскими полями, убрал из функции преобразование типов в запросе - вставка 2млн записей без индексов - 13сек, с индексами - 1min.
Какая-то огромная разница, будто индексы по строкам строятся сильно дольше, чем по числам.

Вопрос с аналогичным тестом, но переложенным в бинарный формат пока актуален. Так же как и вариант передачи массива обьектов без сериализации и последующего парсинга)
...
Рейтинг: 0 / 0
Оптимизация INSERT-ов
    #39933690
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
JDS
Сделал таблицу с со всеми чаровскими полями, убрал из функции преобразование типов в запросе - вставка 2млн записей без индексов - 13сек, с индексами - 1min.
Какая-то огромная разница, будто индексы по строкам строятся сильно дольше, чем по числам.

Вопрос с аналогичным тестом, но переложенным в бинарный формат пока актуален. Так же как и вариант передачи массива обьектов без сериализации и последующего парсинга)


>>будто индексы по строкам строятся сильно дольше, чем по числам.

так и есть... разница до порядка (а в тяжелых случаях - и заметно больше)... сравнение utf8 с учетом локализации - штука ОЧЕНЬ дорогая (по сравнению с сравнением 2 int4 просто по значению).
...
Рейтинг: 0 / 0
Оптимизация INSERT-ов
    #39933730
utf8 это wide string в C/C++
от простого string в тестах regexp, например, в разы отличаются
ну а цифра - это самое удобное/быстрое для компьютера (так то строки это тоже цифры = номер в таблице)
и когда есть возможность, надо всегда юзать их
...
Рейтинг: 0 / 0
Оптимизация INSERT-ов
    #39933741
JDS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Прошу пардона, на самом деле пара запусков была по минуте, позже пробовал еще раз - 35-40сек, то есть разница не такая большая с индексами по чарам.
Ну и кому-то может пригодится товарищ тоже шуршал в этом направлении .
...
Рейтинг: 0 / 0
25 сообщений из 43, страница 1 из 2
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Оптимизация INSERT-ов
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]