Комментарии 15
Вещь полезная, спасибо. Но хотелось бы так же разобраться а какие именно таблицы создаются? Глубоко в 1с не лез.
Так в данном случае это не имеет значения. Каким бы образом через МенеджерВременныхТаблиц или в коде через ПОМЕСТИТЬ не создавалась бы временная таблица в 1С. Все три возможных способа создания таблиц в функции уже учтены.
Лайфхак полезный. Но что-то сомневаюсь, что все временные таблицы, создаваемые 1с, называются tmp_tmp и имеют поле Id
Да кто же его знает, какие именно временные таблицы используются именно в Вашей конфигурации? Одних типовых конфигураций несколько десятков. Берете в зубы auto_explain, отыскиваете запросы, выполняющиеся, например, свыше 10 минут и анализируете источник проблемы. По моему опыту, проблемы почти всегда решаются индексацией таблиц. С индексацией постоянных таблиц проблем нет, а что делать с временными - я описал в статье на примере абстрактной временной таблицы tmp_tmp.
И всё-таки не понятно с идентификацией того что индексируется и по чему.
Абстракции это хорошо, но статье ну очень не хватает более глубокого анализа сути проблемы на конкретных примерах
Ну а по методологии конфигурирования в среде 1С Предприятие 8 есть прямая рекомендация от компании 1С - всегда индексировать поля временных таблиц, если по ним далее ведутся отборы и соединения. Хотя эта рекомендация, на самом деле, далека от истиной во всех инстанциях, и такая индексация реально в меньшем числе случаев даёт заметный выигрыш - в большинстве же случаев его не будет или даже будет лишнее проседание производительности (обычно не сильно большое на запрос - если только он не крутится в большом цикле), то в целом рекомендация к индексации во временных таблицах это скорее благо - но не панацея, и ручной тюнинг всегда желателен. Да и в одной ситуации (и статистики одной и той же БД) может быть один результат, то в других условиях (даже в той же базе) может быть уже противоположный результат - и реальную оценку должен обеспечивать только постоянный сбор статистических данных!
Другая проблема самой платформы 1С Предприятие 8 - это невозможность создать для временной таблице несколько разных индексов - а это порой очень важно, когда таблица используется далее в нескольких местах - приходится довольствоваться неполным, наиболее общим составом индекса, что обычно не очень оптимально. Или дублировать таблицу в отдельные временные таблицы с разными индексами (чаще всего в типовых конфигурациях так и делают). Вот тут создание доп. индекса на лету именно средствами СУБД было бы очень полезно!
И всё-таки не понятно с идентификацией того что индексируется и по чему.
Это просто выходит за рамки статьи. Я даже не уверен, что это можно уместить в одной статье.
Более реальный пример я думал добавить, но побоялся, что тогда статья станет уже совсем про 1С, а не любую систему. Проблема 1С еще в том, что имена временных таблиц там формируются динамически. Имена полей - тоже мало о чем говорят. Поэтому идентифицировать временную таблицу приходится уже строкой ее метаданных, которые я собираю подобной функцией:
CREATE OR REPLACE FUNCTION catch_tmp_tables_info()
RETURNS event_trigger LANGUAGE plpgsql AS $func$
DECLARE
obj record;
metadata text;
BEGIN
FOR obj IN
SELECT *
FROM pg_event_trigger_ddl_commands()
WHERE object_type='table' AND schema_name='pg_temp'
LOOP
SELECT STRING_AGG(attname||$$,$$||attnum::varchar||$$,$$||atttypid::varchar
||$$($$||attlen::varchar||$$,$$||atttypmod::varchar||$$) $$||attnotnull::varchar,$$;$$)
FROM pg_attribute
WHERE attrelid=obj.objid AND attnum>0
INTO metadata;
RAISE NOTICE '% ddl commands: % "%"', tg_tag, obj.object_identity, metadata;
END LOOP;
END;
$func$;
Затем при помощи auto_explain производится анализ, каким временным таблицам действительно нужны индексы и какие именно. После чего, то что выводится в metadata для этих таблиц сохраняется, и в дальнейшем используется для сравнения, чтобы определить, какая же временная таблица создается, прежде чем ее индексировать.
всегда индексировать поля временных таблиц
Вот к этому я точно не призывал. Сначала выявляем проблему, и только если она есть - решаем.
Абстракции это хорошо, но статье ну очень не хватает более глубокого анализа сути проблемы на конкретных примерах
Я Вас услышал. Возможно я не прав. Но, к сожалению, я уже два года с 1С вообще не общаюсь, поэтому конкретный пример брать было просто не откуда. Если такая возможность появится, сделаю уже другую статью, уже не среднего, а сложного уровня, где разберу уже конкретику.
Это просто выходит за рамки статьи. Я даже не уверен, что это можно уместить в одной статье.
Вопрос был не про анализ того почему запрос тормозит и как его оптимизировать. А о технической части реализации проводимой оптимизации начиная со стадии: вот запрос, в нём такие-то временные таблицы, вот эти таблицы нуждаются в индексации по таким-то полям - чтобы это сделать, не меняя исходный запрос нужно сделать вот конкретно то-то и то-то. И так привести в едином кейсе несколько конкретных примеров (ключевое описание статьи начинается со слов "нужно сделать" - всё что до него - это дано).
Более реальный пример я думал добавить, но побоялся, что тогда статья станет уже совсем про 1С, а не любую систему.
Да пишите примеры про любую прикладную СУБД (это же примеры, они всегда к чему-то приложены)
Проблема 1С ещё в том, что имена временных таблиц там формируются динамически. Имена полей - тоже мало о чем говорят
Именно по этой причине и написал свой вопросы Выше. Вы же в статье упоминаете проведение оптимизации для 1С - это сразу и заинтересовало, т.к. знал указанную проблему с идентификацией, но в статье именно её Вы не решали. От того именно для меня ценность статьи сократилась на порядок (может и читать бы не стал). Нет, ну конечно - техника мощная и статья интересная для определённых читателей. Но раз уж упоминаете 1С, то надо до конца разбирать особенности приложения данной технике непосредственно к данной прикладной системе, с учётом имеющихся в ней нюансов, ключевым образом влияющих на возможность применения описываемой техники (хотя я бы просто внёс правки в код запроса внутри конфигурации 1С - и не парился бы - но да - тут уже проблема обновлений и прочее прочее прочее - но оно полюбэ будет надёжнее - а надёжность для меня важнее! Как и эффективность дальнейшего сопровождения; вот только второй индекс во временную таблицу в 1С Предприятие 8 средствами платформы пока не добавить.... хотя вроде бы слышал, что обещали сделать, но может что-то путаю; индексы само собой изменил бы не в тексте исходного запроса, а обработал его программно, перед выполнением).
Поэтому идентифицировать временную таблицу приходится уже строкой ее метаданных, которые я собираю подобной функцией
Вот это уже ближе к сути. Пояснений бы побольше - ну или писать новую статью и делать отсюда на неё отсылку! Хотя по мне - так это всё одна тема и одна статья должны быть! И дело не только в 1С - а вообще о всём разделе идентификации временной таблицы!
Вот к этому я точно не призывал. Сначала выявляем проблему, и только если она есть - решаем.
Я не о том; я как раз ниже всё пояснил. Я о том, что если в стороннем запросе явно не хватает индексов во временной - то это (согласно данной официальной рекомендации) хороший повод написать вендору в суппорт заявку на добавление данных индексов! В идеале вопрос индексирования таблиц (которые гипотетически могут быть нетривиального размера или взаимодействовать с таковыми другими таблицами) хорошо делать настраиваем - т.е. добавлять индексы по некоей опции оптимизации - но до такого мало какие прикладные учётные системы доросли, не то что 1С Предприятие 8. Ну а если индексы уже есть - то если нужно их расширить - это всегда должно легко решаться заявками вендору решения
Спасибо, как раз думаем о тестировании 1С на PostgreSQL. Какую сборку постгреса используете? Сравнивали ли https://releases.1c.ru/project/AddCompPostgre и https://1c.postgres.ru/ ?
Я на стороне интегратора работаю. Разные варианты были. Последние два года вообще с 1С не общаюсь, больше погрузившись в ML. А два года - не малый срок. Поэтому таких рекомендаций давать не возьмусь. Могу только утверждать, что PostgreSQL существенно лучше ведет себя под Linux, чем под Windows. На статью сподвигла уже не первая просьба о помощи в вышеописанной проблеме от коллег и знакомых.
Теперь при создании временной таблицы tmp_tmp любым из трех перечисленных путей, таблица окажется сразу же индексирована
И как минимум два из 3х представляют неудачную реализацию (возможно и третий, но я не в курсе, в каком порядке выполнится создание, событие и вставка данных). Потому что докидывают индекс на этапе создания пустой таблицы, а затем в нее заливаются данные, вызывая постоянные перестроения индекса.
Обычно в проектах с нагрузкой рекомендуют как раз обратное — убирать индексы на массовую загрузку, а затем докидывать их обратно — так все сводится к 1 перестроению.
убирать индексы на массовую загрузку, а затем докидывать их обратно
Я согласен с этим утверждением, но есть два "но".
Во-первых, событийный триггер в PostgreSQL позволяет перехватить только момент создания таблицы, но никак не момент завершения заливки в нее данных. Поэтому, как бы не хотелось индексировать временную таблицу после заливки в нее данных, как это реализовать только средствами БД я не представляю.
Во-вторых, все же у нас временная таблица, а не постоянная. Поэтому ее индекс, в общем случае, вообще на диск может не попасть, оставшись целиком в оперативной памяти, в течении всего времени жизни временной таблицы. Поэтому издержки на его перестроение намного ниже, чем если бы речь шла о постоянной таблице.
Я для себя сравниваю с патчем в расширении внутри 1с.
В расширении оно отключится, если обнаружит, что исходная процедура поменялась. И мы сразу об этом узнаем. Возможно, это будет ложное срабатывание, но мы явно видим проблемный момент и можем поправить до начала работы пользователей.
В тригере СУБД мы вообще не узнаем. Нужны явные проверки рабочести нашей вставки индекса после каждого обновления. Либо в этот метод добавлять какой-то сбор статистики и следить уже за ней, либо всегда держать логирование долгих запросов и ловить тут. Все методы на основе статистики уже внесут задержку — мы узнаем после начала работы пользователей.
мы узнаем после начала работы пользователей
Прошу прощения, а кто-то разве выкатывает обновления сразу на продуктивную среду, без проверки всех ключевых бизнес-процессов на тестовой среде? Вот на тестовой среде, предпочтительно, "минус день", средствами auto_explain все и проверите.
В расширении оно отключится, если обнаружит, что исходная процедура поменялась.
Я несколько раз с таким сталкивался и пришёл к выводу, что надо избегать перетаскивания в расширение целых процедур, особенно больших. Вместо этого лучше менять либо их входные параметры, либо возвращаемый результат, так мы привязываемся не ко всему телу процедуры, а только к её сигнатуре. Конечно, это не всегда возможно, но когда можно, надо к этому стремиться.
При использовании такого метода надо учитывать, что 1С (по крайней мере при работе с MS SQL Server, в PG не изучал) переиспользует временные таблицы - со всей накопившейся структурой метаданных
С SQL Server у меня как-то был интересный случай. При помощи черной магии добавили создание колоночного (columnstore) индекса по временной таблице, участвовавшей в расчёте себестоимости. Первая итерация отрабатывала успешно, но потом начинались проблемы - построчное заполнение таблицы с columnstore-индексом начинает чудовищно тормозить, съедается весь эффект от оптимизации. Более того, из-за того, что таблица была очень простая (одна колонка со ссылками), она переиспользовалась и в других похожих запросах из той же сессии (например, при передаче массива в качестве параметра). Очень быстро все такие таблицы оказывались с columnstore-индексами, что практически парализовывало работу сессии. Вылечилось явным удалением columnstore-индекса после выполнения нужного запроса.
Я это рассказываю не для того, чтобы отвадить читателей от механики из статьи. Просто надо учитывать, что индексы могут "расползтись" и по другим запросам из сессии - не удивляйтесь, если увидите их при отладке там, где их не должно было быть.
1C (и не только) c PostgreSQL