Каталог решений - Миллионы строк в таблицах 1С? Быстрая реструктуризация — не проблема!

Миллионы строк в таблицах 1С? Быстрая реструктуризация — не проблема!

Миллионы строк в таблицах 1С? Быстрая реструктуризация — не проблема!

В наличии

Иногда случаются ситуации, когда в некую таблицу 1С (будь то справочник, регистр сведений или накопления) — необходимо добавить новое поле (реквизит, измерение, ресурс). В обычной ситуации, когда строк в таблице самой БД немного — платформа спокойно справляется с этой задачей. Но что делать, если строк накопилось за время ведения учета 1 млн? А если 10 млн? 100 млн? Более 300 млн? Если Вы не хотите ждать N-ое количество суток в ожидании, когда же закончится реструктуризация, или изобретать другие способы — статья для Вас. Основная идея заключается в том, что соответствие имен метаданных объектов конфигурации 1С (а также их ссылочных взаимосвязей между собой) и имен физических таблиц и колонок в самой БД — эта информация хранится в служебных таблицах этой же БД.

Категория:

Описание

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 тыс. записей и повесить выполнение на «тайм-джоб» в самой СУБД.

Надеюсь, мой опыт кому-нибудь будет полезен.

has been added to your cart:
Оформление заказа