Pull to refresh

Comments 7

Интересно, что узкое место проявилось именно при массовом создании временных таблиц: проблема оказалась не только в запросах, а в конкуренции за LWLock и ограниченном fast path.

Не совсем понял. В ходе статьи вы пишите про временные таблицы, а затем

Мы у себя в lsFusion пошли по третьему пути: сервер приложений держит пул UNLOGGED-таблиц

То есть вы заменили использование временных таблиц на unlogged-таблицы?

Да, пришлось именно в транзакциях на уровне сервера приложения начать использовать вместо temporary обычные unlogged, и раздавать их на сервере приложений. Благо именно в запросах/использовании разницы между ними большой нет (хотя есть другие нюансы).

Но понятно, что не целиком заменили. Во-первых, это используется только там, где тысячи одновременно работающих пользователей. Для меньшей нагрузки "пробка" не образуется. А во-вторых, вне транзакции все равно местами могут использоваться временные (так как там нет долгой блокировки).

Тут будет плюс от unlogged в том, что у вас появляется параллелизм, если конечно результат такого запроса вы не помещаете во временную.
А вообще ваш выбранный 3 вариант это то, как делает платформа 1С. Вот тут в начале статьи объяснение как сервер приложений 1C работает с временными таблицами и какую информацию хранит - https://infostart.ru/1c/articles/2221687/
Также мы сталкивались с подобной проблемой как в вашей текущей статье, вот ее описание - https://infostart.ru/1c/articles/2535895/#Первые результаты и проблемы
А вот ее решение на уровне доработки PostgreSQL - https://habr.com/ru/companies/tantor/articles/924978/#2-2

Тут будет плюс от unlogged в том, что у вас появляется параллелизм, если конечно результат такого запроса вы не помещаете во временную.

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

А вообще ваш выбранный 3 вариант это то, как делает платформа 1С

В смысле 1C использует UNLOGGED таблицы ? Если речь идет о пуле временных таблиц для соединений, то в lsFusion это было сделано давно (до этой статьи). И все равно этого не всегда хватает по ряду причин, так как таблицы, во-первых, выпадают из пула со временем, а, во-вторых, все равно надо создавать их для новых пользователей / подключений (если у вас тысячи подключений и тысячи временных таблиц, то нужны уже десятки, а то и сотни миллионов временных таблиц). На практике в инсталляциях с 2000 одновременно работающих пользователей, общее количество временных таблиц редко превышает 100К (то есть по 50 на соединение).

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

Также мы сталкивались с подобной проблемой как в вашей текущей статье, вот ее описание - https://infostart.ru/1c/articles/2535895/#Первые результаты и проблемы

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

В vanilla PostgreSQL это разные LWLock wait events:

  • LockManager — доступ к информации о heavyweight locks;

  • SInvalRead / SInvalWrite — чтение/запись shared catalog invalidation queue.

Поэтому переход

очередь invalidation → LWLock → значит это причина LWLock:LockManager

в статье не доказан и технически слишком сильно упрощён.

Вполне возможно, что причинная связь косвенная: массовая invalidation заставляет backend'ы перестраивать relcache, снова открывать relations, брать relation locks, и уже это создаёт нагрузку на LockManager. Либо в Tantor есть свои изменения. Но показанного текста недостаточно, чтобы сказать, что ожидание LockManager возникло непосредственно на invalidation queue.

А вот ее решение на уровне доработки PostgreSQL - https://habr.com/ru/companies/tantor/articles/924978/#2-2

Это все замечательно, но в lsFusion используются только открытые и бесплатные технологии с точки зрения лицензий. Везде у нас используется только ванильный PostgreSQL. Наверное, на коммерческих СУБД это бы работало получше, но и на ванильном у нас пока проблемы с разрастанием каталога не так сильно влияют (скорее всего из-за того, что все равно lsFusion гораздо оптимальнее работает с временными таблицами, чем 1С).

В смысле 1C использует UNLOGGED таблицы ? Если речь идет о пуле временных таблиц для соединений, то в lsFusion это было сделано давно (до этой статьи)

Нет, 1С не использует UNLOGGED таблицы, просто вы в 3м варианте написали про переиспользование временных таблиц. Я имел ввиду, что это есть в 1С.
Большое количество временных таблиц в IsFusion генерируют разработчики приложений или на уровне вашей платформы в определенных сценариях зашито использование временных таблиц, что и приводит к их большому количеству?

Конкретно последняя оптимизация была, чтобы вообще заменить их на unlogged и делить между разными подключениями

Интересное решение, но непонятно какой эффект это дало и как оценить профит из фразы "На стенде четыре сохранения потребовали ноль CREATE вместо сорока"? Не добавило ли проблем то, что разные сеансы стали конкурировать за эти UNLOGGED таблицы?

Но показанного текста недостаточно, чтобы сказать, что ожидание LockManager возникло непосредственно на invalidation queue

Да, возможно тест не показателен, ниже в статье был рассказ и об очереди инвалидационных сообщений. Разработчики собирали perf и делали анализ его результатов. Я потом на основе их результатов и писал статью. Что-то мог конечно не раскрыть так, как это мог бы раскрыть разработчик, который делал анализ результатов perf и работал с исходным кодом PostgreSQL.

Большое количество временных таблиц в IsFusion генерируют разработчики приложений или на уровне вашей платформы в определенных сценариях зашито использование временных таблиц, что и приводит к их большому количеству?

Разработчики вообще не знают ничего про SQL и временные таблицы. Все пишется на внутреннем высокоуровневом языке, а затем платформа сама генерирует запросы и при необходимости использует временные таблицы по мере необходимости. К сожалению, местами без них никак по ряду причин. Даже просто в запросах иногда приходится часть подзапроса переделывать на INSERT INTO временную таблицу, а затем с ней JOIN, чтобы у PostgreSQL была правильная статистика по результату этого подзапроса (если план явно ушел не туда).

Интересное решение, но непонятно какой эффект это дало и как оценить профит из фразы "На стенде четыре сохранения потребовали ноль CREATE вместо сорока"? Не добавило ли проблем то, что разные сеансы стали конкурировать за эти UNLOGGED таблицы?

Вообще эту проблему мы диагностировали недавно (так как все-таки пробка возникает не очень часто). Просто на данный момент мы прогнали все на тестах, и включили в работу для нескольких небольших клиентов. Понятно, что сразу это внедрять на самых крупных - не самая лучшая идея. Но пока да - нет еще статистики на крупных клиентах. Правда статья была о проблеме в PostgreSQL, а не о lsFusion.

Другое дело, что архитектурно там крупных изменений нет, так что непосредственно на работу сервера приложений это не должно повлиять. Фактически, там просто изменилось, что если раньше при необходимости получения таблицы смотрелось в пул временных таблиц сессий, то сейчас сначала ищется в общем пуле (с синхронизацией естественно). Понятно, что сам поиск там очень быстрый, а запросов относительно немного (то есть там не будет бутылочного горлышка).

А PostgreSQL разницы что там CREATE TEMPORARY TABLE, что CREATE TABLE UNLOGGED особо нет. Единственно, эти все unlogged таблицы грохаются на старте сервера на всякий, идут в отдельную схему и отдельный tablespace (например, к временным таблицам на диск в памяти).

При этом, если в общем пуле нет, и создать unlogged по какой-то причине нельзя, то идет fallback обратно к временным таблицами.

Sign up to leave a comment.

Articles