Работа с внешними компонентами, такими как ПоставщикДанных в связке с 1sqlite, позволяет значительно расширить возможности 1С 7.7. Однако при выводе больших списков документов или использовании сложных отборов мы часто сталкиваемся с тем, что «движок» базы данных строит неоптимальные планы запросов. Разберем, почему возникают «жуткие тормоза» при прокрутке списка и как это исправить.
Когда мы используем ПоставщикДанных, компонент автоматически генерирует SQL-запросы для получения порции данных. Основная проблема кроется в конструкции IN (...), которая возникает при отборе документов по нескольким видам (например, Приход, Продажа, Списание). Оптимизатор SQLite при виде IN часто пытается использовать составной индекс, в который первым полем входит iddocdef, но делает это крайне неэффективно, сканируя индекс целиком или выбирая неверный путь исполнения.
Кроме того, если в запросе присутствует LEFT JOIN к таблицам шапок документов для получения дополнительных полей (например, Сумма), каждое «листание» списка вызывает пересчет этих соединений для всех строк выборки, что мгновенно «подвешивает» интерфейс.
Чтобы заставить SQLite работать быстрее, необходимо вмешаться в процесс формирования текста запроса внутри класса ПоставщикДанных. Существует специфический прием: если перед именем поля в SQL-запросе поставить символ +, это «блокирует» использование индекса по данному полю для оптимизатора, заставляя его искать альтернативный, более быстрый путь.
Разберем, как модифицировать метод ПолучитьТекстИсточникаСбора в модуле класса. Наша задача — добавить этот блокирующий «плюс» при формировании фильтра по видам документов.
// В методе ПолучитьТекстИсточникаСбора находим блок формирования фильтра:
КоличествоДокументов = ВидыДокументов.Количество();
Если КоличествоДокументов > 0 Тогда
ТекстИсточника = ТекстИсточника + "
|" + КлючевоеСлово + " (+ТекущийОбъект.iddocdef "; // Добавляем плюс для блокировки
КлючевоеСлово = "and";
КонецЕсли;
После применения этого изменения, при наличии нескольких видов документов в отборе, SQLite не будет пытаться перебирать записи через индекс iddocdef, а переключится на индекс по idjournal или индексы по дате, что значительно ускорит процесс.
Если блокировки индекса недостаточно, необходимо полностью пересмотреть способ формирования фильтра в SQL-запросе. Мы можем отказаться от стандартного IN в пользу более контролируемого построения строки запроса. Рассмотрим пример реализации:
Если ЭтоSQL = 1 Тогда
КоличествоДокументов = ВидыДокументов.Количество();
Если КоличествоДокументов > 0 Тогда
ТекстИсточника = ТекстИсточника + "
|" + КлючевоеСлово + " (ТекущийОбъект.iddocdef ";
КлючевоеСлово = "and";
КонецЕсли;
СтрокаВидыДокументов = "";
Для НомерВида = 0 По КоличествоДокументов - 1 Цикл
ВидДокумента = ВидыДокументов.Получить(НомерВида);
ИДОбъекта = МетаДата.ИДДокумента(ВидДокумента);
СтрокаВидыДокументов = СтрокаВидыДокументов + ?(НомерВида = 0, "", ",") + ИДОбъекта;
КонецЦикла;
ТекстИсточника = ТекстИсточника + ?(КоличествоДокументов = 1, "= ", "in (") + СтрокаВидыДокументов + ?(КоличествоДокументов = 1, "", ")") + ")";
Иначе
ТекстИсточника = ТекстИсточника + "
|" + КлючевоеСлово + " (ТекущийОбъект.idjournal = :ЖурналДокументов." + ВидЖурнала + " ) ";
КонецЕсли;
Важные рекомендации по оптимизации:
LEFT JOIN для получения сумм документов в журнале, рассмотрите возможность выноса этих данных (например, реквизит Сумма) непосредственно в журнал документов. Это избавит вас от необходимости делать соединения таблиц при отрисовке каждой строки, что является самым «тяжелым» процессом.IDJOURNAL + DATE + TIME + IDDOC. Он является наиболее подходящим для журнальных запросов в 1С 7.7.1sqlite.dll. Ошибки в работе с виртуальными таблицами и конструкцией IN часто исправляются в новых версиях драйверов.VBCCR17.OCX. Это современная замена старым библиотекам MS Common Controls, которая стабильно работает в современных операционных системах.Проанализировав эти шаги, вы сможете добиться мгновенной отрисовки даже в самых нагруженных журналах документов вашей системы. Помните: главный враг производительности в SQL-журналах — это лишние джойны и неверно выбранные индексы в условиях WHERE.