В процессе разработки на платформе 1С:Предприятие 7.7 программисты часто сталкиваются с проблемой производительности при работе с документами, содержащими огромное количество строк (десятки и сотни тысяч). Стандартные методы, такие как КоличествоСтрок(), при вызове через объект могут выполняться крайне медленно — вплоть до нескольких минут. В этой статье мы разберем, как эффективно решать задачу подсчета строк с помощью внешней компоненты 1SQLite и как правильно работать с контекстом формы для получения оперативных данных.
Прежде чем переходить к решениям, проанализируем ситуацию: почему стандартный метод КоличествоСтрок() работает так долго? Когда вы создаете объект через СоздатьОбъект("Документ.ВидДока"), находите нужный документ и вызываете метод КоличествоСтрок(), платформа 1С 7.7 выполняет полную десериализацию объекта. Это означает, что система считывает из базы данных абсолютно все реквизиты всех строк табличной части, чтобы полностью воссоздать объект в оперативной памяти. Если в документе 200 000 строк, это может потребовать загрузки сотен мегабайт данных, хотя вам нужно лишь одно число.
Если документ уже записан в базу данных, самым быстрым способом получить количество его строк является прямой SQL-запрос через компоненту 1SQLite. Этот метод не загружает данные строк в память 1С, а выполняет агрегатную функцию COUNT(*) непосредственно на уровне движка базы данных.
Рассмотрим пример кода для выполнения такого запроса:
База = СоздатьОбъект("SQLiteBase");
База.Открыть(":memory:"); // Или к файлу БД
Запрос = База.НовыйЗапрос();
ТекстЗапроса = "
|SELECT
| COUNT(*) as Кво
|FROM
| [ДокументСтроки.ВашВидДокумента] as Док
|WHERE
| Док.IDDOC = :ТекДок";
Запрос.УстановитьПараметр("ТекДок", ВыбДок);
ТЗ = Запрос.Выполнить();
КвоСтрок = ТЗ.ПолучитьЗначение(1, "Кво");
Важный нюанс: Прямой запрос видит только те данные, которые уже физически записаны на диск (в файлы DBF или таблицы SQL). Если пользователь открыл документ, добавил 100 строк, но еще не нажал кнопку «Записать», 1SQLite об этих строках не узнает.
Выясним причину, по которой работа в открытой форме кажется быстрее. Экспериментально доказано, что метод КоличествоСтрок(), вызванный непосредственно из контекста открытой формы (или через переданный контекст), работает мгновенно. Это происходит потому, что в контексте формы данные уже десериализованы и находятся в оперативной памяти процесса.
Если вам нужно получить количество строк в открытом документе, включая те, что еще не записаны, используйте обращение к текущему контексту:
// В модуле формы документа
Кво = КоличествоСтрок(); // Работает мгновенно
Если же вам нужно получить данные извне, можно использовать «хак» с передачей контекста или параметров через ОткрытьФорму. Рассмотрим такой пример:
// Код в обработке, которой нужно узнать количество строк в открытом документе
Конт = "ПолучитьКво";
ОткрытьФорму(ВыбДок, Конт);
// В самом документе в ПриОткрытии():
Если Форма.Параметр = "ПолучитьКво" Тогда
Форма.Параметр = КоличествоСтрок();
СтатусВозврата(0); // Закрываем форму сразу, не отображая
Возврат;
КонецЕсли;
Для очень больших документов, которые постоянно редактируются, хорошей практикой считается ведение собственного счетчика. Посмотрим, как это реализовать:
ВсегоСтрок (числовой).ПриЗаписи() или при интерактивном добавлении/удалении строк обновляйте это значение.КоличествоСтрок().Это позволит вам в любой момент мгновенно получить значение реквизита шапки, не прибегая к тяжелым вычислениям.
Проанализируем результаты замеров для документа объемом 260 000 строк:
Объект.КоличествоСтрок(): ~240 секунд (4 минуты).КоличествоСтрок() из контекста формы: Мгновенно.В связке с 1SQLite часто используют расширение FormEx. Если документ открыт, вы можете обратиться к объекту TableBox, который управляет визуальным отображением строк. Через методы FormEx можно получить количество строк в табличном поле формы без обращения к объекту документа, что также работает крайне быстро и отражает текущее состояние «экранных» данных.
Резюме: Если документ закрыт — используйте 1SQLite. Если документ открыт и редактируется — используйте контекст формы. Никогда не используйте Объект.КоличествоСтрок() для документов с количеством строк более 10 000 в циклах или часто вызываемых процедурах.