В процессе разработки и доработки прикладных решений на платформе 1С:Предприятие (в частности, в конфигурации «1С:Документооборот») разработчики нередко сталкиваются с ситуацией, когда стандартной длины реквизита Наименование объекта метаданных не хватает. Платформа жестко ограничивает длину стандартного наименования справочников, задач и бизнес-процессов лимитом в 150 символов. Попытка расширить это поле стандартными средствами или через расширение конфигурации не дает результата.
В связи с этим возникает необходимость создать собственный дополнительный реквизит для хранения развернутого текста (например, от 500 до 1000 символов). При этом у разработчиков закономерно появляются вопросы: нужно ли делать длину строки кратной степени двойки (512, 1024), как реквизиты такой длины хранятся в реляционной СУБД, можно ли их индексировать и как грамотно организовать архитектуру вывода данных в списки и запросы. Разберем эти технические нюансы подробно.
Среди разработчиков нередко встречается мнение, что при выходе за пределы коротких строк длину реквизита необходимо округлять вверх до значений, кратных 512 или 1024 байтам. Выясним причину появления этого заблуждения и то, как на самом деле устроено хранение данных в СУБД.
Современные СУБД (Microsoft SQL Server, PostgreSQL, Oracle), с которыми работает платформа 1С:Предприятие, сохраняют строки ограниченной длины в типах данных переменной длины — NVARCHAR(N) или VARCHAR(N). Для таких типов данных СУБД резервирует на диске объем, равный фактическому количеству записанных символов с учетом кодировки, плюс 2 байта служебного заголовка для фиксации длины записи.
Никакой технической необходимости выравнивать границу строки до 512 или 1024 символов нет. Если бизнес-логика требует ограничить текст 500, 550 или 600 символами — устанавливайте ровно то значение, которое необходимо. СУБД не выделяет под пустые или короткие строки фиксированные 512 байт, а для длинных строк не требует кратности блоку диска на уровне одного поля таблицы.
Проанализируем ситуацию, когда для быстрого поиска разработчик пытается включить свойство Индексировать у строкового реквизита длиной 500–600 символов и сталкивается с ошибкой платформы при реструктуризации базы данных.
Причина кроется в архитектурных ограничениях используемой СУБД. Рассмотрим этот механизм на примере Microsoft SQL Server:
_IDRRef), которая имеет тип binary(16) и забирает 16 байт из лимита индекса.900 - 16 = 884 байта.884 / 2 = 442 символа.Таким образом, предельная длина строкового реквизита, который еще можно включить в индекс в MS SQL Server вместе с ссылкой, составляет ровно 442 символа. Если в индекс входят дополнительные поля или разделители данных, допустимая длина строки становится еще меньше. Поэтому установить индексацию для реквизита длиной 500 или 600 знаков невозможно — СУБД просто отклонит создание такого индекса.
Когда индексация по подстроке невозможна стандартным B-Tree индексом, встает выбор между ограниченной строкой (например, Строка(600)) и строкой неограниченной длины. Сравним поведение этих типов данных:
ПОДСТРОКА. Кроме того, вывод неограниченных строк в динамические списки часто приводит к просадке производительности клиент-серверного обмена.ГДЕ, ВЫБОР и соединять по точному равенству.Если реквизит будет заполнен практически всегда и его длина предсказуема (в пределах 500–600 символов), выбор ограниченной строки Строка(600) является более предпочтительным, чем строка неограниченной длины.
Рассмотрим, как правильно выстроить архитектуру приложения, если стандартного поля Наименование (150 символов) объективно недостаточно для отображения сути задачи.
Классический подход проектирования метаданных в 1С предполагает разделение информации по назначению:
Наименование оставляем длиной 150 символов. В него записывается краткая формулировка задачи, которая легко помещается в динамические списки, не перегружает экранные формы и быстро читается пользователем.ПолноеНаименование или ОписаниеЗадачи с типом Строка(600). В него вносится подробное описание.Если требуется, чтобы во всех ссылочных полях и отчетах при выборе задачи выводился текст из расширенного реквизита, переопределим формирование представления в модуле менеджера объекта. Посмотрим на пример кода:
Процедура ОбработкаПолученияПолейПредставления(Поля, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
Поля.Добавить("Наименование");
Поля.Добавить("ПолноеНаименование");
КонецПроцедуры
Процедура ОбработкаПолученияПредставления(Данные, Представление, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
Если ЗначениеЗаполнено(Данные.ПолноеНаименование) Тогда
Представление = Данные.ПолноеНаименование;
Иначе
Представление = Данные.Наименование;
КонецЕсли;
КонецПроцедуры
Такой подход позволяет сохранить стандартный реквизит для системных нужд, но выводить пользователю детальную строку в интерфейсе и печатных формах.
Поскольку B-Tree индекс на строки более 442 символов наложить нельзя, поиск по подстроке вида ПОДОБНО "%Текст%" по строке в 600 символов приведет к полному сканированию таблицы (Table Scan или Index Scan). На больших объемах данных задач это вызовет критическое падение производительности.
Разберем два эффективных способа организовать поиск по длинному реквизиту:
ХэшНаименования (например, Строка(32) для MD5 или Строка(64) для SHA-256). При записи объекта вычисляйте хэш от длинной строки, а в запросах делайте отбор по индексированному полю хэша, после чего дополнительно сравнивайте саму строку:
ВЫБРАТЬ
Задачи.Ссылка КАК Задача
ИЗ
Задача.ЗадачаИсполнителя КАК Задачи
ГДЕ
Задачи.ХэшНаименования = &ИскомыйХэш
И Задачи.ПолноеНаименование = &ИскомаяСтрока
Подведем итог: при добавлении реквизита под расширенное наименование не нужно искусственно округлять длину до 512 или 1024 знаков — используйте точную оценку потребностей (например, Строка(600)). Учитывайте, что проиндексировать такое поле средствами СУБД не удастся из-за лимита в 442 символа. Для поиска используйте механизм полнотекстового поиска платформы, а в пользовательских списках по возможности выводите краткий вариант, подтягивая полный текст только при детальном просмотре объекта.