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

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

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

В этой статье мы подробно разберем, почему возникает эта ошибка, как устроены индексы в файловой СУБД 1С, и рассмотрим пошаговые методы устранения данной проблемы.

Выясняем причину: почему файловая база не принимает данные?

В файловой СУБД «1С:Предприятие» (формат базы данных 1Cv8.1CD) действует жесткое техническое ограничение: суммарная длина ключа любого индекса не может превышать 1920 байт.

В клиент-серверных СУБД (MS SQL Server, PostgreSQL, IBM DB2) эти лимиты гораздо шире или обрабатываются СУБД иначе (например, за счет динамического переполнения строк), поэтому база на сервере работает без сбоев. Но при попытке «сжать» эту структуру в файловый формат происходит аварийное завершение операции.

Для составных индексов (таких как уникальный индекс по измерениям регистра _ByDims) длина рассчитывается как сумма длин всех входящих в него полей. Давайте посмотрим на формулу расчета размера полей в индексе в байтах:

  1. Строка (String): Рассчитывается как Длина * 3 + 2. Платформа 1С резервирует в индексе до 3 байт на один символ (для полноценной поддержки кодировки Unicode/UTF-8) плюс 2 служебных байта. Например, если в вашем регистре есть измерение типа «Строка» с длиной 1000 символов, то только это одно поле займет в индексе 3002 байта (1000 * 3 + 2). Это мгновенно превышает лимит файловой базы в 1920 байт, даже без учета остальных полей индекса!
  2. Ссылка (UUID): Всегда занимает ровно 16 байт.
  3. Дата (Date): Занимает 8 байт.
  4. Булево (Boolean): Занимает 1 байт.
  5. Число (Number): Размер рассчитывается на основе заявленной разрядности.

Почему не помогает снятие флажка «Индексировать»?

Многие разработчики пытаются зайти в свойства измерения проблемного регистра и переключить свойство «Индексирование» в положение «Не индексировать». Однако это не решает проблему.

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

Следовательно, если у вас в измерениях регистра присутствует длинная строка (например, «Номенклатура для печати» с длиной 1000 символов), платформа физически не сможет создать таблицу этого регистра в файловой базе.


Шаг 1. Локализация проблемного объекта

Для начала нам нужно понять, какой именно объект конфигурации скрывается под системным именем таблицы СУБД. Проанализируем текст ошибки из темы:

Ошибка СУБД: Длина ключа индекса превышает максимально допустимую '_AccumRg23916_ByDims@ (_Fld1002, _Period, _Fld23909RRef...)'

Префикс _AccumRg однозначно указывает на то, что перед нами **Регистр накопления** (Accumulation Register). Пятизначный номер 23916 — это внутренний идентификатор метаданных.

Чтобы сопоставить имя физической таблицы с объектом конфигурации 1С, выполним следующие действия:

  1. Если у вас есть доступ к SQL-базе, запустите Конфигуратор.
  2. Используйте специальные обработки для получения структуры базы данных (например, «Структура базы данных» с портала Инфостарт или аналогичные встроенные инструменты).
  3. Также вы можете получить структуру таблиц программно через вызов метода встроенного языка ПолучитьСтруктуруХраненияБазыДанных().

Рассмотрим пример кода, который можно запустить во внешней обработке в исходной SQL-базе, чтобы быстро найти имя регистра по имени таблицы СУБД:


СтруктураБД = ПолучитьСтруктуруХраненияБазыДанных();
Для Каждого СтрокаТаблицы Из СтруктураБД Цикл
    Если СтрокаТаблицы.ИмяТаблицыХранения = "_AccumRg23916" Тогда
        Сообщить("Проблемный объект конфигурации: " + СтрокаТаблицы.ИмяТаблицы);
        Прервать;
    КонецЕсли;
КонецЦикла;

После выполнения данного скрипта мы определим имя регистра (например, РегистрНакопления.ПродажиПокупателям) и имена полей (например, измерение НоменклатураДляПечати с типом «Строка» длиной 1000).


Шаг 2. Разбор вариантов решения проблемы

Рассмотрим несколько эффективных способов обхода ограничения файловой базы.

Вариант А. Изменение структуры регистра (рекомендуемый архитектурный подход)

Хранить длинные строковые данные в измерениях регистра — это грубая архитектурная ошибка. Измерения предназначены для разрезов учета (ключей доступа к данным). Текст длиной 1000 символов (например, полное наименование номенклатуры для печати или многострочное примечание) должен храниться либо в справочнике, либо в крайнем случае в **реквизитах** регистра.

Реквизиты и ресурсы регистра накопления не входят в состав основного кластерного индекса _ByDims, поэтому их длина никак не влияет на ограничение в 1920 байт. Выполним рефакторинг регистра по шагам:

  1. Разверните копию базы на SQL-сервере (например, используя бесплатную версию MS SQL Server Developer Edition или PostgreSQL).
  2. Откройте Конфигуратор и найдите наш проблемный регистр.
  3. Создайте новый **Реквизит** регистра (например, НоменклатураДляПечатиРеквизит) с типом «Строка» нужной длины.
  4. Напишите и запустите обработку, которая перенесет данные из измерения в новый реквизит для всех существующих записей в базе данных.
  5. Удалите старое измерение НоменклатураДляПечати. При необходимости переименуйте новый реквизит.
  6. Скорректируйте модули проведения документов, которые записывают движения в этот регистр, чтобы данные писались в реквизит, а не в измерение.
  7. Сохраните конфигурацию базы данных (выполните реструктуризацию).
  8. Выгрузите базу в файл .dt. Теперь этот файл без проблем загрузится в файловую версию!

Вариант Б. Сокращение длины строкового измерения

Если по какой-то причине перенести строку в реквизиты невозможно, нам придется сократить предельную длину строкового измерения до приемлемых размеров. Помните: чтобы строковое поле гарантированно помещалось в индекс файловой базы вместе с другими стандартными измерениями (такими как Период, Регистратор, Номенклатура-ссылка), его длина не должна превышать **150–200 символов**.

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

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


ВЫБРАТЬ
    Продажи.Регистратор КАК ДокументДвижения,
    Продажи.НоменклатураДляПечати КАК ДлиннаяСтрока,
    ДЛИНА(Продажи.НоменклатураДляПечати) КАК ДлинаСимволов
ИЗ
    РегистрНакопления.ПродажиПокупателям КАК Продажи
ГДЕ
    ДЛИНА(Продажи.НоменклатураДляПечати) > 150

После выявления документов-регистраторов, которые записали аномально длинные строки, выполните следующие действия:

  1. С помощью внешней обработки обрежьте значение измерения до 150 символов во всех найденных записях регистра и перезапишите наборы движений.
  2. В Конфигураторе уменьшите длину строкового измерения регистра до 150 символов.
  3. Выполните реструктуризацию базы данных.
  4. Выгрузите базу в .dt и загрузите в файловую версию.

Вариант В. Что делать, если нет SQL-сервера для исправления структуры?

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

В этом случае рекомендуем воспользоваться бесплатной СУБД PostgreSQL:

  1. Установите локально бесплатную сборку PostgreSQL, адаптированную для работы с «1С:Предприятием».
  2. Через утилиту администрирования серверов 1С создайте новую серверную базу данных, указав параметры подключения к локальному серверу PostgreSQL.
  3. Запустите Конфигуратор созданной пустой базы и загрузите туда ваш файл .dt (на PostgreSQL загрузка пройдет успешно, так как там лимиты индексов позволяют это сделать).
  4. Выполните исправление структуры регистра (по варианту А или варианту Б).
  5. После успешного сохранения изменений выгрузите базу обратно в файл .dt. Теперь его можно легко развернуть в обычную файловую базу 1Cv8.1CD на любом компьютере.

Резюме

Ошибка превышения длины ключа индекса в файловой базе 1С — это всегда сигнал о неоптимальном проектировании метаданных. Перенос длинных строк из измерений в реквизиты регистров не только решит проблему с совместимостью файлового формата, но и существенно повысит общую производительность вашей информационной базы в будущем.

← На главную