Мільйони рядків у таблицях 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 * FROMUPP2.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._AccumRgT17

Бо у нас там мільйони рядків – невідомо, наскільки швидко це відпрацює. На жаль, для тестів у мене не було таких обсягів даних, тому однозначної відповіді не можу дати. Але, якщо потрібно - можна трохи ускладнити ці запити, оновлювати ці поля в таблицях порціями, наприклад по 100 тис. записів і повісити виконання на "тайм-джоб" у самій СУБД.

Сподіваюся, мій досвід комусь буде корисним.