При выгрузке информационной базы из клиент-серверного варианта (SQL) в файл выгрузки (.dt) и последующей попытке загрузить её в файловую базу разработчики нередко сталкиваются с ошибкой СУБД: «Длина ключа индекса превышает максимально допустимую '_InfoRgXXXXX_ByDims'». При этом на стороне SQL Server база данных функционировала без сбоев. Проанализируем, почему возникает такое поведение платформы «1С:Предприятие» и как правильно решить данную проблему.
Для понимания корня проблемы разберем механизм построения индексов в различных СУБД:
1CD) действует строгое ограничение — суммарная длина составного ключа любого индекса не может превышать 1920 байт. При этом файловый движок вычисляет потенциальную длину ключа статически, ориентируясь на объявленные максимальные длины типов в метаданных конфигурации, а не на фактический размер записанных строк. Если в регистре объявлено несколько строковых полей большой длины (например, по 500 символов), платформа рассчитывает предельный размер строки с учетом кодировки символов и служебных заголовков. В результате суммарный размер превышает лимит в 1920 байт еще на этапе создания таблиц и индексов при загрузке .dt.NVARCHAR) осуществляется динамически. Таблица и индекс создаются успешно, а ошибка возникает только в тот момент, когда реальная суммарная длина данных конкретной строки превышает установленный лимит. Если фактические строки короткие (например, содержат всего 10–20 символов), база на SQL Server продолжает работать без ошибок.Часто разработчики пытаются установить в свойствах измерений регистра флаг «Не индексировать», однако это не решает проблему. Рассмотрим, почему так происходит.
Имя индекса из текста ошибки заканчивается суффиксом _ByDims. Этот индекс является основным кластерным индексом таблицы регистра сведений и строится платформой принудительно по всем измерениям регистра (а также по полю Период для периодических регистров). Именно этот индекс гарантирует уникальность комбинации измерений. Свойство «Индексировать» у отдельного измерения управляет лишь созданием дополнительного отдельного индекса по этому полю. Отключить построение основного составного индекса _ByDims стандартными средствами метаданных невозможно, пока поля остаются в составе измерений.
Самое правильное и архитектурно выверенное решение — пересмотреть структуру регистра. Измерения регистра должны служить только для обеспечения уникальности записи и быстрого отбора срезов. Поля, содержащие произвольный длинный текст, описания или примечания, не должны являться измерениями.
Разберем по шагам порядок действий:
_ByDims, суммарная длина ключа уменьшится до разрешенных пределов..dt.Бывают ситуации, когда длинная строка (например, внешний составной идентификатор, URL или токен длиной 500 символов) действительно должна входить в ключ уникальности. В таком случае разберем паттерн хеширования:
ХешИдентификатора с типом Строка фиксированной длины (например, 32 символа для MD5 или 64 символа для SHA-256).Идентификатор перенесем в Реквизиты регистра.
Хеширование = Новый ХешированиеДанных(ХешФункция.MD5);
Хеширование.Добавить(ИсходныйИдентификатор);
ЗаписьРегистра.ХешИдентификатора = Хеширование.ХешСумма;
ЗаписьРегистра.Идентификатор = ИсходныйИдентификатор;
Если строковые данные часто повторяются между записями, рационально заменить строковое измерение на ссылочный тип:
СправочникСсылка.ВнешниеИдентификаторы).Если серверной базы больше нет и на руках остался только поврежденный файл .dt, загрузить его напрямую в файловую базу не удастся. Попытки удалить индексы через SQL-консоль бессмысленны, так как файл выгрузки сохраняет только конфигурацию и логические данные, а индексы строятся заново при загрузке.
Разберем по шагам аварийный план действий в такой ситуации:
.dt (на сервере СУБД загрузка пройдет успешно, так как лимиты там проверяются иначе)..dt — после этого база без ошибок загрузится в файловый вариант.