Почему тормозит запись номенклатуры в 1С 7.7 на SQL и как это исправить

Программист 1С v7.7 Управленческий учет Торговля и дистрибуция
← На главную

Работа в классической конфигурации 1С:Предприятие 7.7, особенно в связке с SQL-сервером, при больших объемах данных часто преподносит сюрпризы в виде внезапных «тормозов». Одной из самых распространенных проблем является замедление при записи или редактировании элементов справочника Номенклатура. Рассмотрим детально, почему это происходит, как диагностировать проблему и какие шаги предпринять для оптимизации системы.

Анализируем симптомы и проводим замер производительности

Первым делом нам необходимо выяснить, на каком именно этапе происходит задержка. Если система «подвисает» в момент нажатия кнопки «ОК» или при записи элемента, нам поможет штатный инструмент — Замер производительности. В конфигураторе или режиме отладки запустим процесс и выполним запись элемента. Проанализируем типичный замер производительности, который часто встречается в подобных ситуациях:


Глобальный модуль | 1018 | Пока ЦеныТовара.ПолучитьЭлемент() = 1 Цикл | 501981 | 85.191610 | 51.78
Справочник.Номенклатура.Форма | 1328 | глЗаписьПериодическихРеквизитов(Контекст); | 1 | 76.893254 | 46.74

Обратим внимание на первую строку. Мы видим более 500 000 итераций в цикле. Это критический показатель. Выясним причину: почему при записи одного товара система перебирает полмиллиона записей? Как правило, это связано с обновлением формы списка, которое инициируется сразу после закрытия или записи карточки товара. Если в форме списка выведены колонки с ценами или остатками, система начинает пересчитывать их для всех видимых строк.

Разбираем проблему «пустого владельца» в справочниках

Одной из наиболее коварных ловушек в 1С 7.7 является поведение метода ИспользоватьВладельца(). Рассмотрим стандартную функцию получения цены, которая часто модифицируется программистами:


Функция глВернутьЦену(Товар, КатегорияЦены) Экспорт
    Перем ЦеныТовара;
    ЦеныТовара = СоздатьОбъект("Справочник.Цены");
    ЦеныТовара.ИспользоватьВладельца(Товар);
    ЦеныТовара.ВыбратьЭлементы();
    Пока ЦеныТовара.ПолучитьЭлемент() = 1 Цикл
        Если ЦеныТовара.ПометкаУдаления() = 1 Тогда
            Продолжить;
        КонецЕсли;
        Если ЦеныТовара.КатегорияЦены = КатегорияЦены Тогда
            Возврат ЦеныТовара.ТекущийЭлемент();
        КонецЕсли;
    КонецЦикла;
КонецФункции

Проанализируем ситуацию: если переменная Товар окажется пустой (например, при создании нового элемента, который еще не записан в базу, или из-за ошибки передачи контекста в форму списка), метод ИспользоватьВладельца(Товар) фактически сбрасывает фильтр. В результате ВыбратьЭлементы() начинает перебирать весь справочник цен целиком по всей базе данных. Если у вас 500 000 записей о ценах, система будет честно просматривать каждую для каждой строки списка номенклатуры.

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


Если (ПустоеЗначение(Товар) = 1) ИЛИ (Товар.Выбран() = 0) Тогда
    Возврат "";
КонецЕсли;

Оптимизируем выборку данных в SQL-версии

Даже при корректном владельце метод ВыбратьЭлементы() в цикле — это не самое быстрое решение для SQL-базы. Рассмотрим варианты ускорения этого процесса:

  1. Использование метода ВыбратьЭлементыПоРеквизиту: Если у вас в справочнике Цены включена сортировка (индекс) по реквизиту КатегорияЦены, можно использовать этот метод. Однако стоит помнить, что в 7.7 метод ИспользоватьВладельца() и ВыбратьЭлементыПоРеквизиту() не всегда эффективно работают вместе на уровне SQL-запроса.
  2. Переход на черные запросы: Использование объекта Запрос вместо объектного перебора справочника позволяет SQL-серверу более эффективно использовать свои индексы.
  3. Прямые запросы (1C++ или ToySQL): Это самый радикальный и эффективный метод. Прямой SQL-запрос через внешние компоненты позволяет получить нужную цену за миллисекунды, минуя тяжелые механизмы объектной модели 1С 7.7.

Влияние периодических реквизитов и таблицы 1SCONST

В замере производительности мы видели выполнение процедуры глЗаписьПериодическихРеквизитов. В системе 1С 7.7 периодические реквизиты хранятся в огромной общей таблице 1SCONST. При записи элемента номенклатуры система обращается к этой таблице для записи новых значений цен или налогов.

Проанализируем причины замедления в этой части:

Специфика работы в распределенных базах (УРБД)

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

Рекомендация: Убедитесь, что все обмены проходят успешно. Если в таблице 1SUPDTS скопились миллионы записей, которые уже не актуальны, рассмотрите возможность их принудительной очистки (после консультации со специалистом и создания резервной копии).

Регламентные операции на стороне SQL Server

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

  1. Обновление статистики: SQL-оптимизатор строит план выполнения запроса на основе статистики распределения данных. Если статистика устарела (например, после массовой загрузки товаров), SQL может выбрать неоптимальный путь поиска данных. Выполните UPDATE STATISTICS для ключевых таблиц (справочники, 1SCONST, 1SUPDTS).
  2. Очистка процедурного кэша: В редких случаях «плохой» план запроса застревает в памяти. Команда DBCC FREEPROCCACHE может помочь сбросить текущие планы и заставить сервер построить их заново.
  3. Проверка блокировок: Если запись тормозит только в моменты активной работы пользователей, возможно, происходят блокировки таблиц. Используйте SQL Profiler, чтобы выявить, не конфликтует ли запись номенклатуры с тяжелыми отчетами, которые читают те же таблицы.

Итоговый чек-лист для исправления ситуации

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

  1. Добавьте в глобальные функции получения цен и остатков (глВернутьЦену и аналогичные) жесткую проверку на Выбран() = 1 для переданного объекта.
  2. Проверьте форму списка номенклатуры. Если там есть вызов функций пересчета в колонках, попробуйте временно их отключить и проверить скорость записи.
  3. Если база SQL — перепишите получение цен для списка на прямые запросы. Это уберет сотни тысяч бесполезных итераций.
  4. Проверьте таблицу 1SUPDTS. Если она переполнена — завершите все обмены или проведите профилактику УРБД.
  5. Выполните полное обслуживание индексов и статистики в SQL Management Studio.

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

← На главную