Почему при работе с Поставщиком Данных в 1С 7.7 журнал документов открывается или листается очень медленно?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

Работа с внешними компонентами, такими как ПоставщикДанных в связке с 1sqlite, позволяет значительно расширить возможности 1С 7.7. Однако при выводе больших списков документов или использовании сложных отборов мы часто сталкиваемся с тем, что «движок» базы данных строит неоптимальные планы запросов. Разберем, почему возникают «жуткие тормоза» при прокрутке списка и как это исправить.

Анализ причин снижения производительности

Когда мы используем ПоставщикДанных, компонент автоматически генерирует SQL-запросы для получения порции данных. Основная проблема кроется в конструкции IN (...), которая возникает при отборе документов по нескольким видам (например, Приход, Продажа, Списание). Оптимизатор SQLite при виде IN часто пытается использовать составной индекс, в который первым полем входит iddocdef, но делает это крайне неэффективно, сканируя индекс целиком или выбирая неверный путь исполнения.

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

Решение 1: Оптимизация SQL-запроса через блокировку неэффективного индекса

Чтобы заставить SQLite работать быстрее, необходимо вмешаться в процесс формирования текста запроса внутри класса ПоставщикДанных. Существует специфический прием: если перед именем поля в SQL-запросе поставить символ +, это «блокирует» использование индекса по данному полю для оптимизатора, заставляя его искать альтернативный, более быстрый путь.

Разберем, как модифицировать метод ПолучитьТекстИсточникаСбора в модуле класса. Наша задача — добавить этот блокирующий «плюс» при формировании фильтра по видам документов.


// В методе ПолучитьТекстИсточникаСбора находим блок формирования фильтра:
КоличествоДокументов = ВидыДокументов.Количество();
Если КоличествоДокументов > 0 Тогда
    ТекстИсточника = ТекстИсточника + "
    |" + КлючевоеСлово + " (+ТекущийОбъект.iddocdef "; // Добавляем плюс для блокировки
    КлючевоеСлово = "and";
КонецЕсли;

После применения этого изменения, при наличии нескольких видов документов в отборе, SQLite не будет пытаться перебирать записи через индекс iddocdef, а переключится на индекс по idjournal или индексы по дате, что значительно ускорит процесс.

Решение 2: Переработка логики фильтрации в SQL

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


Если ЭтоSQL = 1 Тогда
    КоличествоДокументов = ВидыДокументов.Количество();
    Если КоличествоДокументов > 0 Тогда
        ТекстИсточника = ТекстИсточника + "
        |" + КлючевоеСлово + " (ТекущийОбъект.iddocdef ";
        КлючевоеСлово = "and";
    КонецЕсли;
    
    СтрокаВидыДокументов = "";
    Для НомерВида = 0 По КоличествоДокументов - 1 Цикл
        ВидДокумента = ВидыДокументов.Получить(НомерВида);
        ИДОбъекта = МетаДата.ИДДокумента(ВидДокумента);
        СтрокаВидыДокументов = СтрокаВидыДокументов + ?(НомерВида = 0, "", ",") + ИДОбъекта;
    КонецЦикла;
    
    ТекстИсточника = ТекстИсточника + ?(КоличествоДокументов = 1, "= ", "in (") + СтрокаВидыДокументов + ?(КоличествоДокументов = 1, "", ")") + ")";
Иначе
    ТекстИсточника = ТекстИсточника + "
    |" + КлючевоеСлово + " (ТекущийОбъект.idjournal = :ЖурналДокументов." + ВидЖурнала + " ) ";
КонецЕсли;

Важные рекомендации по оптимизации:

  1. Вынос реквизитов: Если вы активно используете LEFT JOIN для получения сумм документов в журнале, рассмотрите возможность выноса этих данных (например, реквизит Сумма) непосредственно в журнал документов. Это избавит вас от необходимости делать соединения таблиц при отрисовке каждой строки, что является самым «тяжелым» процессом.
  2. Индексация: Проверьте наличие индекса IDJOURNAL + DATE + TIME + IDDOC. Он является наиболее подходящим для журнальных запросов в 1С 7.7.
  3. Версии компонентов: Всегда используйте актуальные сборки 1sqlite.dll. Ошибки в работе с виртуальными таблицами и конструкцией IN часто исправляются в новых версиях драйверов.
  4. Совместимость: Если вы работаете на Windows 10/11, и стандартные элементы управления журнала вызывают ошибки, рассмотрите замену на компоненты, использующие VBCCR17.OCX. Это современная замена старым библиотекам MS Common Controls, которая стабильно работает в современных операционных системах.

Проанализировав эти шаги, вы сможете добиться мгновенной отрисовки даже в самых нагруженных журналах документов вашей системы. Помните: главный враг производительности в SQL-журналах — это лишние джойны и неверно выбранные индексы в условиях WHERE.

← На главную