Нередко при доработке типовых конфигураций разработчики сталкиваются с требованием пользователей: выводить в документах списания или отчетах произвольный текст из первичного документа (например, подробное поле Содержание услуги из реализации). Самым простым решением на первый взгляд кажется добавление строкового измерения прямо в регистр накопления. Однако строка вида Строка(400) в измерении регистра накопления быстро приводит к серьезным техническим проблемам. Проанализируем, почему такое решение недопустимо и какими способами можно правильно перестроить архитектуру учета.
Выясним технические причины, по которым строковое измерение приводит к сбоям системы:
Период плюс все измерения регистра. В Microsoft SQL Server лимит размера ключа индекса составляет 900 байт (в некоторых версиях — до 1700 байт), а в файловых базах .1CD — 1920 байт. Платформа 1С сохраняет строки в формате NVARCHAR, где на каждый символ выделяется 2 байта. Поле Строка(400) сразу забирает 800 байт. Добавив стандартные ссылки (номенклатура, контрагент, договор по 16 байт на UUID) и служебные поля, мы получаем гарантированную ошибку реструктуризации базы данных при обновлении.Рассмотрим несколько правильных архитектурных вариантов решения этой задачи.
Если текст содержания уникален для каждой строки документа реализации и требуется только для последующего списания и вывода в отчет комитенту, правильнее всего полностью убрать текстовое измерение из регистра накопления. Сам текст выносится в непериодический регистр сведений, подчиненный регистратору.
Разберем по шагам реализацию этого механизма:
РеализованныеТоварыКомитентов удаляем строковое измерение. Регистр восстанавливает нормальную свертку остатков.СодержаниеУслугКомитентов с режимом записи Подчинение регистратору.ИдентификаторСтроки (тип Число(10,0) или УникальныйИдентификатор) и ресурс Содержание (неограниченная строка).
ВЫБРАТЬ
Остатки.Номенклатура КАК Номенклатура,
Остатки.КоличествоОстаток КАК Количество,
ЕСТЬNULL(ДанныеСодержания.Содержание, "") КАК Содержание
ИЗ
РегистрНакопления.РеализованныеТоварыКомитентов.Остатки(&Период, ) КАК Остатки
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СодержаниеУслугКомитентов КАК ДанныеСодержания
ПО Остатки.Партия = ДанныеСодержания.Регистратор
И Остатки.НомерСтрокиДокумента = ДанныеСодержания.ИдентификаторСтроки
Если текст в содержании услуг периодически повторяется, его можно нормализовать с помощью отдельного справочника. В регистр накопления помещается ссылка на элемент этого справочника (размер поля в индексе составит всего 16 байт вместо сотен байт текста).
Чтобы избежать появления дублирующих записей в справочнике при сохранении неограниченных строк, применим механизм расчета хеш-суммы (например, MD5 или CRC32):
СодержанияУслуг. В реквизитах создаем Содержание (строка неограниченной длины) и индексируемый реквизит ХешСумма (строка 32 символа).СправочникСсылка.СодержанияУслуг.Посмотрим на пример функции получения ссылки на содержание:
Функция ПолучитьСсылкуНаСодержание(ТекстСодержания) Экспорт
Хеширование = Новый ХешированиеДанных(ХешФункция.MD5);
Хеширование.Добавить(СокрЛП(ТекстСодержания));
ХешСтрока = Строка(Хеширование.ХешСумма);
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Спр.Ссылка КАК Ссылка
|ИЗ
| Справочник.СодержанияУслуг КАК Спр
|ГДЕ
| Спр.ХешСумма = &ХешСумма
| И Спр.Содержание = &Содержание";
Запрос.УстановитьПараметр("ХешСумма", ХешСтрока);
Запрос.УстановитьПараметр("Содержание", СокрЛП(ТекстСодержания));
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Возврат Выборка.Ссылка;
Иначе
НовыйОбъект = Справочники.СодержанияУслуг.СоздатьЭлемент();
НовыйОбъект.Содержание = СокрЛП(ТекстСодержания);
НовыйОбъект.ХешСумма = ХешСтрока;
НовыйОбъект.Записать();
Возврат НовыйОбъект.Ссылка;
КонецЕсли;
КонецФункции
Это наиболее надежный архитектурный подход, используемый в современных типовых конфигурациях (таких как ERP, КА и БП 3.0 в учете НДС). Вместо набора текстовых полей создается пара: справочник КлючиАналитикиУчета и непериодический независимый регистр сведений АналитикаУчета.
Разберем логику работы механизма:
КлючАналитики.Этот метод гарантирует абсолютную компактность таблиц итогов регистра накопления и исключает появление дублей данных при повторных операциях.
Если регистр накопления уже заполнен движениями с длинными строками, изменение структуры через конфигуратор может привести к аварийной остановке СУБД из-за перестроения индексов. Выполним переход по шагам: