Почему возникает ошибка «Длина ключа индекса превышает максимально допустимую» при загрузке базы из SQL в файловый вариант?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При выгрузке информационной базы из клиент-серверного варианта (SQL) в файл выгрузки (.dt) и последующей попытке загрузить её в файловую базу разработчики нередко сталкиваются с ошибкой СУБД: «Длина ключа индекса превышает максимально допустимую '_InfoRgXXXXX_ByDims'». При этом на стороне SQL Server база данных функционировала без сбоев. Проанализируем, почему возникает такое поведение платформы «1С:Предприятие» и как правильно решить данную проблему.

Выясним причину: различия файловой СУБД и SQL Server

Для понимания корня проблемы разберем механизм построения индексов в различных СУБД:

  1. Ограничение встроенной файловой СУБД 1С: в файловом формате (1CD) действует строгое ограничение — суммарная длина составного ключа любого индекса не может превышать 1920 байт. При этом файловый движок вычисляет потенциальную длину ключа статически, ориентируясь на объявленные максимальные длины типов в метаданных конфигурации, а не на фактический размер записанных строк. Если в регистре объявлено несколько строковых полей большой длины (например, по 500 символов), платформа рассчитывает предельный размер строки с учетом кодировки символов и служебных заголовков. В результате суммарный размер превышает лимит в 1920 байт еще на этапе создания таблиц и индексов при загрузке .dt.
  2. Поведение Microsoft SQL Server: в SQL Server ограничение на составной ключ индекса составляет 900 байт (для стандартных кластерных индексов). Однако контроль размера для полей переменной длины (NVARCHAR) осуществляется динамически. Таблица и индекс создаются успешно, а ошибка возникает только в тот момент, когда реальная суммарная длина данных конкретной строки превышает установленный лимит. Если фактические строки короткие (например, содержат всего 10–20 символов), база на SQL Server продолжает работать без ошибок.

Почему не помогает отключение индексирования измерений?

Часто разработчики пытаются установить в свойствах измерений регистра флаг «Не индексировать», однако это не решает проблему. Рассмотрим, почему так происходит.

Имя индекса из текста ошибки заканчивается суффиксом _ByDims. Этот индекс является основным кластерным индексом таблицы регистра сведений и строится платформой принудительно по всем измерениям регистра (а также по полю Период для периодических регистров). Именно этот индекс гарантирует уникальность комбинации измерений. Свойство «Индексировать» у отдельного измерения управляет лишь созданием дополнительного отдельного индекса по этому полю. Отключить построение основного составного индекса _ByDims стандартными средствами метаданных невозможно, пока поля остаются в составе измерений.

Способ 1. Нормализация структуры регистра (перенос полей в ресурсы или реквизиты)

Самое правильное и архитектурно выверенное решение — пересмотреть структуру регистра. Измерения регистра должны служить только для обеспечения уникальности записи и быстрого отбора срезов. Поля, содержащие произвольный длинный текст, описания или примечания, не должны являться измерениями.

Разберем по шагам порядок действий:

  1. Проанализируем состав измерений проблемного регистра сведений. Если поля, такие как «Представление», «Копия» или длинный комментарий, не определяют уникальность записи, перенесем их в состав Ресурсов или Реквизитов регистра.
  2. Поскольку ресурсы и реквизиты не входят в составной индекс _ByDims, суммарная длина ключа уменьшится до разрешенных пределов.
  3. Перед реструктуризацией убедимся, что после переноса полей оставшиеся измерения не создадут дубликатов записей. Если дубли возможны, предварительно обработаем и схлопнем повторяющиеся строки.
  4. Применим изменения в конфигураторе и выполним повторную выгрузку базы в .dt.

Способ 2. Хеширование длинных строковых идентификаторов

Бывают ситуации, когда длинная строка (например, внешний составной идентификатор, URL или токен длиной 500 символов) действительно должна входить в ключ уникальности. В таком случае разберем паттерн хеширования:

  1. Создадим новое измерение ХешИдентификатора с типом Строка фиксированной длины (например, 32 символа для MD5 или 64 символа для SHA-256).
  2. Исходное длинное поле Идентификатор перенесем в Реквизиты регистра.
  3. При записи данных программно рассчитываем контрольную сумму от исходной строки и записываем её в измерение:
    
    Хеширование = Новый ХешированиеДанных(ХешФункция.MD5);
    Хеширование.Добавить(ИсходныйИдентификатор);
    ЗаписьРегистра.ХешИдентификатора = Хеширование.ХешСумма;
    ЗаписьРегистра.Идентификатор = ИсходныйИдентификатор;
    
  4. Это позволит кардинально сократить длину ключа в индексе и исключить ошибку переполнения.

Способ 3. Переход на ссылочный тип данных (Справочник)

Если строковые данные часто повторяются между записями, рационально заменить строковое измерение на ссылочный тип:

  1. Создадим вспомогательный справочник для хранения уникальных строковых значений.
  2. Заменим тип строкового измерения в регистре на ссылку на данный справочник (например, СправочникСсылка.ВнешниеИдентификаторы).
  3. Посмотрим на размер: любая ссылка в платформе 1С занимает в индексе ровно 16 байт (размер UUID). Замена строк длиной в сотни символов на 16-байтные ссылки полностью устраняет превышение лимита индекса.

Что делать, если база на SQL уже недоступна?

Если серверной базы больше нет и на руках остался только поврежденный файл .dt, загрузить его напрямую в файловую базу не удастся. Попытки удалить индексы через SQL-консоль бессмысленны, так как файл выгрузки сохраняет только конфигурацию и логические данные, а индексы строятся заново при загрузке.

Разберем по шагам аварийный план действий в такой ситуации:

  1. Развернем бесплатную версию клиент-серверной СУБД (например, PostgreSQL или Microsoft SQL Server Express).
  2. Создадим пустую базу на сервере 1С:Предприятия и загрузим в неё имеющийся файл .dt (на сервере СУБД загрузка пройдет успешно, так как лимиты там проверяются иначе).
  3. Откроем конфигуратор серверной базы и выполним нормализацию структуры регистра (уменьшим длины строк или перенесем лишние поля в ресурсы).
  4. Обновим конфигурацию базы данных.
  5. Создадим новый файл .dt — после этого база без ошибок загрузится в файловый вариант.
← На главную