Как ускорить реструктуризацию 1с
Данная статья является анонсом новой функциональности.
Не рекомендуется использовать содержание данной статьи для освоения новой функциональности.
Полное описание новой функциональности будет приведено в документации к соответствующей версии.
Полный список изменений в новой версии приводится в файле v8Update.htm.
Мы разработали новый механизм реструктуризации базы данных, который позволяет ускорить обновление конфигурации в среднем в 3-4 раза, а в отдельных случаях на порядки. Ускорение достигается за счёт минимизации манипуляций над данными и максимального их переноса на уровень системы управления базой данных (СУБД).
Что такое реструктуризация?
Реструктуризация это изменение структуры и состава таблиц базы данных, и перенос имеющихся данных в изменённые таблицы. Обычно реструктуризация выполняется в тот момент, когда вы нажимаете Обновить конфигурацию базы данных в Конфигураторе. Но выполняется она не каждый раз.
Реструктуризация выполняется тогда, когда изменения конфигурации требуют появления новых колонок или таблиц в базе, или когда меняется тип существующей колонки. Например, вы добавили реквизит к справочнику, добавили документ, или изменили тип имеющегося реквизита с Число на Строка. В этих случаях потребуется реструктуризация.
Если рассматривать реструктуризацию с точки зрения манипулирования данными, то существует база данных и схема данных, которая соответствует конфигурации базы данных. После того, как вы обновляете конфигурацию базы данных, создаются новые структуры данных, в которые переносятся старые данные.
«Традиционная» реструктуризация
В процессе реструктуризации последовательно анализируются все объекты конфигурации. Не углубляясь в подробности можно сказать, что для каждого объекта выполняется:
- Анализ его изменений;
- Создание новых таблиц в базе данных, которые соответствуют новой структуре объекта;
- Перенос данных.
Из этих трёх шагов перенос данных занимает наибольшее количество времени. При этом сами операции переноса данных могут быть простыми и сложными.
Например, к простым и быстрым операциям относятся те, которые вызваны добавлением или удалением столбцов таблицы. В этом случае отдельным запросом создаётся новая таблица (с изменённой структурой) и данные переносятся в неё.
Все остальные операции являются сложными, могут занимать длительное время, и для их выполнения требуется участие Конфигуратора (или серверной части платформы, если обновление выполняется на сервере). Потому что процесс переноса данных может сопровождаться различными вспомогательными действиями, обусловленными спецификой 1С:Предприятия.
Например, может потребоваться удаление ссылок на несуществующие объекты, изменение предопределённых данных, предварительная фильтрация данных (для удаления движений, соответствующих удаляемым регистраторам), проверка уникальности номеров и кодов, проверка количества уровней вложенности справочника и корректности его иерархии, и другие.
Новый механизм реструктуризации
Главное изменение заключается в том, что оптимизация реструктуризации достигнута не за счёт локальных изменений «традиционного» механизма, а за счёт создания полностью нового механизма реструктуризации.
Это непростая и трудоёмкая задача, потому что механизм реструктуризации должен обеспечивать транзакционность изменений, то есть надежность и целостность базы данных во всех случаях. Механизм должен быть готов к тому, что процесс реструктуризации может прерваться в любой момент (в результате сбоя, например), и при этом система должна остаться в консистентном состоянии. То есть либо в виде старой версии, либо в виде новой версии. Старый механизм для этого создавал новые версии изменённых таблиц, и заполнял их. А потом подменял все старые версии на новые.
Новый механизм тоже обеспечивает транзакционность, но более сложным способом.
Кроме этого новый механизм основан на ряде идей, которые позволили получить значительное ускорение:
- Максимальное количество операций делегируется на уровень СУБД, потому что это наиболее близкая к данным часть, и она имеет большие возможности изменения данных.
- Обрабатываются только те таблицы СУБД, в которых изменения конфигурации могут вызвать изменение данных. В «традиционном» механизме это было не всегда так. Например, при изменении реквизита табличной части документа копировались данные и основной таблицы, и всех табличных частей документа.
- Табличные части реструктуризируются отдельно. При этом возможно отдельное «пореквизитное» их изменение. Например, если вы добавили реквизит к табличной части, то к таблице просто добавляется новый столбец, без модификации основной таблицы.
На основе этих идей мы достигли максимальной оптимизации на тех изменениях конфигурации, которые приводят к следующим операциям с данными:
- Добавление или удаление столбцов таблиц. Эти операции проводятся теперь на текущих таблицах (раньше создавались новые таблицы и в них переносились данные). Необходимость добавления или удаления столбцов возникает, например, при добавлении или удалении реквизитов, при изменении некоторых свойств объекта конфигурации (иерархия справочника и столбец _ParentID) и др.
- Добавление или удаление индексов. Просто создаётся новый индекс, без создания новых таблиц и переноса данных. Эти операции выполняются, если вы установили индексирование у реквизита, например.
- Изменение существующих индексов. Также выполняется без создания таблиц и переноса данных. Например, кластерный индекс регистра сведений меняется тогда, когда вы добавляете измерение.
В других операциях перенос данных требуется как и раньше, но практически всегда (в большей части операций) он осуществляется на уровне СУБД. Данные переносятся единым запросом. Это может быть INSERT для новых таблиц, или UPDATE существующих таблиц.
Конечно, существуют такие изменения, которые всё равно проходят обработку на сервере с выгрузкой данных построчно. Например, преобразование строки в число, или в дату. Такие операции нецелесообразно делать на уровне СУБД, к тому же они довольно редко встречаются. Но наиболее частые изменения проводятся всё же на уровне СУБД, одним запросом на одну таблицу.
В среднем ускорение достигает 4 раз. Это, конечно, зависит от конкретной конфигурации, от конкретных изменений, и даже конкретных данных. В отдельных случаях ускорение может быть до 20 раз. Такое возможно, например, при удалении реквизита в большой таблице, или если изменения затрагивают маленькие таблицы, но сам объект при этом является довольно большим.
Помимо ускорения есть и другой положительный момент. Во многих случаях не перестраиваются индексы. Это позволяет сохранить их актуальность, сохранить статистику, сократить место, требуемое для реструктуризации.
Мы провели несколько сравнительных экспериментов на реальных информационных базах, и получили следующие результаты:
- Добавление реквизитов к документам и измерений к регистрам сведений. База 400 Гб. Новый механизм позволяет ускорить реструктуризацию с 2 часов до 15 минут.
- Изменение режима совместимости с 8.2.19 на 8.3.6. База 6 Тб. Ускорение с 5 дней до 12 часов.
Особенности текущей реализации
Новый механизм реструктуризации мы планируем включить в версию 8.3.11 в статусе бета. Он реализован только на сервере, причём на сервере должна быть установлена Java 8.
Чтобы использовать новый механизм реструктуризации, вы можете запустить Конфигуратор в пакетном режиме. Кроме этого в файле conf.cfg вы также можете указать необходимость использования нового механизма. Тогда новая реструктуризация будет выполняться при нажатии Конфигурация – Конфигурация базы данных – Обновить конфигурацию базы данных на сервере. Если никаких специальных действий не предпринимать (просто установить новую платформу), то стандартно будет использоваться старый механизм.
Пока поддерживаются только две СУБД: MS SQL Server и PostgreSQL.
На текущий момент мы оптимизировали реструктуризацию не всех объектов конфигурации, а только основных:
- Планов обмена,
- Справочников,
- Документов,
- Журналов документов,
- Планов видов характеристик,
- Планов счетов,
- Регистров сведений,
- Регистров накопления,
- Регистров бухгалтерии.
Для перечисленных объектов (кроме регистров) оптимизированы любые их изменения. Для регистров мы оптимизировали реструктуризацию движений и реструктуризацию таблиц регистрации изменений. Операции пересчёта итогов и пересчёта срезов для регистра сведений мы пока не оптимизировали. Однако, несмотря на это, использование нового механизма уже даёт существенное ускорение всего обновления регистров в целом.
Мы рассматриваем возможность увеличения охвата операций и расширения состава объектов конфигурации, реструктуризация которых оптимизирована в новом механизме.
300 млн. строк? Что это? Разве такое возможно? Да, и если кто-то не может представить себе такую ситуацию - поверьте, вполне! В моей практике в ИБ 1С, в регистре сведений, хранились все изменения всех-всех ключевых документов/справочников/регистров сведений сильно измененной, большой и сильно допиленной УПП - создания, изменения и т.д. За год там накопилось около 320 млн строк. И, как всегда это бывает, понадобилось добавить колонку, то есть новый реквизит в эту таблицу. Вот алгоритм действий, с помощью которого можно довольно быстро решить задачу:
Все описанное актуально для ИБ, развернутых в клиент-серверном варианте. Я тестировал на MS SQL, но думаю, на остальных СУБД - все тоже самое. Тесты проводились на типовой УПП 1.3.78.1. Платформа 8.3.5.1460, MS SQL EXPRESS.
1. Делаем резервную копию базы-источника средствами СУБД. Подчеркиваю, средствами СУБД, так как нам нужен полный зеркальный снимок нашей базы данных. Не используем выгрузку в dt, да собственно, раз Вы столкнулись с такими объемами - то навряд ли подумаете об этом.
2. Из резервной копии поднимаем точно такую же базу, регистрируем ее на сервере приложений 1С. Далее, в моем примере UPP1 - база-источник, UPP2 - ее точная свежая копия.
3. Для начала добавим в базе UPP2 в справочник Номенклатура строковый реквизит, к примеру назовем его СтрокаПокупатель, тип строка (50), неиндексируемое. После того, как мы подняли из резервной копии новую базу, подключаемся к ней средствам СУБД, например с помощью Management Studio. Теперь нам надо выяснить, какая же таблица БД соответствует имени метаданных "Справочник.Номенклатура". Я для этой цели использовал удобную обработку из состава мобильных Инструментов Разработчика, но у кого ее нет под рукой - легко вытащить всю нужную информацию с помощью функции ПолучитьСтруктуруХраненияБазыДанных. Итак, я выяснил, что в моей конфигурации это таблица _Reference95. Будем считать, что именно в этой таблице у меня миллионы строк. Произведем ее очистку скриптом:
TRUNCATE TABLE UPP2.dbo._Reference95
Данная инструкция - самый быстрый способ очистить таблицу от данных. Но, для миллионных объемов - придется подождать, конечно во много раз меньше, по сравнению с типовой реструктуризацией.
4. Запускаем конфигуратор для UPP2. Снимаем нужный объект с поддержки, добавляем реквизит - все как обычно. Обновляем конфигурацию базы данных, так как строки из таблицы мы удалили - реструктуризация и обновление пройдет быстро.
5. Теперь нам снова нужно выяснить, какая колонка в БД SQL была добавлена в нашу таблицу справочника "Номенклатура". У меня это колонка имеет название _Fld33662, тип nvarchar(50), NULL. Идем в базу UPP1 с помощью MenStudio. Находим таблицу_Reference95 и добавляем столбец. Как добавить столбец, выполнить произвольный запрос - будем считать, что это все умеют, а кто не умеет - разберется самостоятельно. Обращаю внимание, что добавлять столбцы в уже существующую и заполненную таблицу можно только установив флаг "разрешить Null", иначе инструкция ALTER TABLE, которая изменяет таблицу - не сработает.
6. Выгоняем пользователей из UPP1. Далее выполняем следующий скрипт:
BEGIN TRAN Tr1
DELETE FROM UPP1.dbo.Config
DELETE FROM UPP1.dbo.DBSchema
DELETE FROM UPP1.dbo.Files
DELETE FROM UPP1.dbo.Params
INSERT INTO UPP1.dbo.Config
SELECT *
FROM UPP2.dbo.Config
INSERT INTO UPP1.dbo.DBSchema
SELECT *
FROM UPP2.dbo.DBSchema
INSERT INTO UPP1.dbo.Files
SELECT *
FROM UPP2.dbo.Files
INSERT INTO UPP1.dbo.Params
SELECT *
FROM UPP2.dbo.Params
COMMIT TRAN Tr1
7. Открываем конфигуратор UPP1, видим, что наш реквизит добавился в справочник "Номенклатура". Запускаем предприятие и выясняем, что новому реквизиту действительно соответствует колонка _Fld33662. Пробуем открыть любой элемент справочника или выполнить запросов, прочитав новый реквизит. Если прочиталось - все получилось. Для очистки совести можно выполнить проверку ссылочной целостности конфигурации в меню тестирования и исправления. У меня проблем не возникло.
8. Обращаю внимание, что мы добавили в таблицу новое поле, значение которого во всех строках этой таблицы, существовавших ранее - Null. Для справочников и регистров сведений - я считаю, это допустимо. Особенно, если вновь добавленный реквизит примитивного типа.
Для более сложной ситуации, когда например нужно добавить измерение ссылочного типа в таблицу регистра накоплений - здесь уже нужно анализировать и принимать решение о целесообразности таких действий.
Алгоритм тот же самый, но теперь колонки в искомую базу из ее зеркальной копии мы будем добавлять не в одну таблицу, а в две - таблицу самих движений и таблицу итогов. И, если измерение индексируемое - выясняем, какой индекс добавился (добавится 1-н некластерный индекс) и как изменится кластерный индекс и вручную выполняем эти изменения в базе-источнике для обеих таблиц. Смотрим состав полей индекса в зеркале, переносим в источник. Так как в таблицах регистров накопления значения ссылочных полей не допускают типа Null, то в этой ситуации придется выполнить скрипт:
UPDATE UPP1.dbo._AccumRg17789
SET UPP1.dbo._AccumRg17789._Fld33665RRef = Convert(binary(16), 0)
FROM UPP1.dbo._AccumRg17789
UPDATE UPP1.dbo._AccumRgT17798
SET UPP1.dbo._AccumRgT17798._Fld33665RRef = Convert(binary(16), 0)
FROM UPP1.dbo._AccumRgT17798
Так как у нас там миллионы строк - неизвестно, насколько быстро это отработает. К сожалению, для тестов у меня не было таких объемов данных, поэтому однозначного ответа дать не могу. Но, если очень нужно - можно немного усложнить эти запросы, обновлять эти поля в таблицах порциями, например по 100 тыс. записей и повесить выполнение на "тайм-джоб" в самой СУБД.
Итак. Программисты 80lvl скорее всего знают все и даже больше, чем описано в статье, поэтому эта публикация будет ориентирована в первую очередь на новичков. А так как у новичка скорее всего ни репутации и стартмани - все скрипты я не буду прикреплять, а выложу в статье.
Поехали. Предположим в вашей конфигурации есть некий документ, с 5 табличными частями. В СУБД (в нашем примере PosgreSQL, но все ниже сказанное справедливо и других СУБД) такой документ предстанет в виде 6 таблиц
Предположим вам необходимо добавить реквизит в табличную часть _document39_vt415, узнать какая именно табличная часть можно либо специальными обработками, либо просто посмотрев несколько записей из таблицы в самой СУБД. Что произойдет далее, точнее что сделает платформа 1С, она создаст копии всех 6 (!) таблиц документа и начнет копирование в них данных из старых таблиц - начнется реструктуризация. Процесс этот, мягко говоря, не быстрый. Почему я вообще пишу эту статью, потому что в моем случаи: количество документов (записей в _document39 было 1М) и записей в табличных частях 25М, процесс реструктуризации документа средствами 1С занял 48 часов. Так вот мы попытаемся обмануть платформу.
Продолжаем, добавляем реквизит в табличную часть в конфигураторе, у меня это число длинной 10, точность 0 (во время всех манипуляций его можно не закрывать), сохраняем, но не обновляем. Переименовываем все таблицы документа в pgAdmin или чем вы там пользуетесь (у меня это пара pgAdmin и EMS SQL Manager PostgreSQL), например _document39 в _document39_src
И создаем копии наших переименованных таблиц (пустые) с первоначальными именами, в нашем примере делаем пустую копию _document39_src с именем _document39.
Копии я создавал в EMS SQL Manager лишь потому, что в нем это проще, но можно и в pgAdmin. В нем надо в контекстном меню таблицы выбрать Скрипты - CREATE и в окне SQL редактора изменить имя таблицы на новое.
Если посмотреть в предприятии, у нас нет ни одного документа.
Теперь, когда 1С считает, что у нас нет документов, в конфигураторе жмем обновить, реструктуризация проходить мгновенно (если возникнут ошибки, жмем обновить еще раз, до тех пор, пока не появится окно о принятии изменений).
Смотрим какое имя получила новая колонка таблицы, которая соответствует новому реквизиту.
У меня это _fld1097. Возвращаемся к нашей исходной таблице, которую мы переименовали в _document39_src, добавляем новую колонку в нее
Ставим значение по умолчанию, здесь 0 и жмем ОК. Весь процесс занял около 1 часа (в 48 раз быстрее). После того как колонка создана, стираем значение по умолчанию и переименовываем таблицу обратно (у нас в _document39)
Запускаем предприятие и проверяем. Радуемся или плачем.
Итак, это мы добавили реквизит, рассмотрим теперь случай, если нам надо изменить тип реквизита, например, было число (5, 2), надо число (10, 4), или добавить индексов.
Тут есть два варианта.
Вариант первый. Создаем копии таблиц и заливаем в них данные из основной таблицы
После этого очищаем исходные таблицы, т.е. доходим до момента, когда 1С думает, что у нас нет записей в таблицах документ. Делаем все необходимые изменения в конфигураторе и обновляем. Теперь нам надо вернуть данные назад
Запускаем предприятие и проверяем. Радуемся или плачем.
Вариант второй. Кто-то считает, что INSERT INTO работает медленно, поэтому можно использовать следующие скрипты, работающие не с копиями таблицы а с файлами на диске
где 'e:/_document39' это файл в корне диска е.
Скрипт загружающий данные обратно
На этом, пожалуй все.
Как видно, процесс это все равно долгий (около 18 часов у меня). Что мы получили, около 19 часов против 48 при изменении типа реквизита и добавлении индексов, и около 1 часа против 48 часов при добавлении реквизита.
PS. У меня есть подозрение, что на других СУБД реструктуризация средствами платформы будет быстрей. К тому же у меня стоял старый PosgresSQL, еще 8.2.4-3.1
Заинтересовал один вопрос. "Реструктуризация таблиц информационной базы" через конфигуратор тоже самое что и "Сжатие базы данных средствами SQL" или всё же чем-то отличаются?
(1) "Реструктуризация таблиц информационной базы" - пересоздаёт каждую таблицу занаво, а "Сжатие базы данных средствами SQL" только сжимает уже имеющиеся таблицы?
(3) Ну кто знал, думал "Реструктуризация таблиц информационной базы" оставлена как сжатие для совместимости с файловым вариантом базы.
(4) А то, что один ещё пункт есть "сжатие", ни на что не намекает?
(6) Значит, украли )))
Но и вообще, как можно подумать, что "реструктуризация" может быть эквивалентна "сжатию"? .
Скидку сделаю на предновогоднее настроение
(7) А почему сжатие не может быть выбрасыванием из базы удаленных записей (пересозданием таблиц)?
(8) По сути у меня при сжатии лог вырастает на объём базы данных после сжатия.
(8) Что значит "не может"? Именно это оно и делает.
(9) Так лог тоже сжать надо потом, если он у тебя растёт.
(0) ну рассказывай, в чём беда-то, из-за чего сжатием начал интересоваться? База "распухла" до целых 10 Гб?
(11) ну может и не пересоздает, но по сути копирует занаво, но уже без удалённых записей.
(12) Удалил итоги, записи регистров за период, а потом применил сжатие средствами SQL, вот думаю есть ли смысл запускать из конфигуратора реструктуризацию.
(19) "посредством удаления" и "копируются только данные" - как-то уж совсем разные вещи.
(20) А как ещё может происходить удаление? Допустим в середине файла нужно удалить данные. Удалили, в середине пустота, в конце файла ещё есть данные, размер файла остался прежним, наверное нужно перенести данные которые в конце в эту пустую область в середине, верно?
Или как вариант в начале сделать указатель, что остальная часть данных находится по другому адресу.
(11) > +10 но сжатие не пересоздаёт таблицы. А по месту.
Ага.
А ещё оно сразу в процессе пиццу с колой (или пивом в зависимости от желаний пользователя) материализует прямо перед монитором чтобы не скучно ждать было.
В FileMon, например, не судьба посмотреть перед тем как (или вместо того чтобы) сказки рассказывать?
(23) А ты маленький ребёнок или красивая девушка, чтобы я тебе сказки рассказывал?
+ 23 но таблицы и оно и правда не пересоздаёт, оно просто новую БД делает (с такой же структурой) и туда все данные копирует.
(25) Кто? 1с? При сжатии таблиц? Или МСскл создаёт новую бд?
(26) Мальчик, а ты точно конфигуратор от клиент серверной версии видел?
P.S. "Сжатие таблиц" есть только в файловой.
(27) Девочка, если ты не прочитала всю тему, то зачем лезешь туда, где большие дядьки важные вопросы обсуждают?
(28) Да я вообще сюда в основном захожу почитать как дилетанты других жить учат.
Иногда даже регистрирую рандомный ник и отвечаю что-то, но обычно не слушают.
Иногда вот как сейчас зачем-то местным троллям типа тебя пытаюсь зачем-то открыть глаза на их недалёкость.
P.S. В хамстве мне конечно до местного контингента как до луны, уел. Сдаюсь.
Миста — веселый ресурс со своими эксклюзивными тараканами Ymryn
Читайте также: