В процессе разработки конфигураций и внешних обработок на платформе 1С:Предприятие регулярно возникает необходимость проверить, содержит ли справочник хотя бы одну запись, либо получить точное число существующих элементов. При этом критически важно не создавать избыточную нагрузку на сервер баз данных: считывание всех полей таблицы, выгрузка данных в промежуточную таблицу значений или ручной обход строк в цикле на больших объемах информации приводят к существенным задержкам.
Разберем наиболее эффективные, проверенные и стандартизированные способы решения этих задач средствами языка запросов и объектной модели 1С.
Если перед нами стоит задача только узнать, пуст справочник или в нем уже есть данные, нам не требуется пересчитывать все записи таблицы. Достаточно запросить у СУБД ровно одну любую запись с помощью конструкции ВЫБРАТЬ ПЕРВЫЕ 1 и проверить результат выполнения методом Пустой().
Посмотрим на классический пример такого запроса:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| 1 КАК ПолеКонстанта
|ИЗ
| Справочник.Номенклатура КАК Номенклатура";
РезультатЗапроса = Запрос.Выполнить();
СправочникПуст = РезультатЗапроса.Пустой();
Если СправочникПуст Тогда
// Действия, если данных нет
КонецЕсли;
Обратим внимание на выборку константы 1 вместо реальных реквизитов или ссылок: серверу не приходится тратить время на чтение строк переменной длины или разыменование полей, он возвращает фиктивное значение при обнаружении первой же физической строки в таблице.
Когда требуется выяснить точное количество элементов, хранящихся в справочнике, оптимальным вариантом является применение агрегатной функции КОЛИЧЕСТВО(*). СУБД выполняет подсчет на уровне движка базы данных и передает на сторону 1С только одно итоговое число.
Рассмотрим пример кода:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КОЛИЧЕСТВО(*) КАК ВсегоЭлементов
|ИЗ
| Справочник.Номенклатура КАК Номенклатура";
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
ВсегоЭлементов = Выборка.ВсегоЭлементов;
КонецЕсли;
В среде разработчиков часто возникает вопрос: есть ли разница в производительности между КОЛИЧЕСТВО(*) и КОЛИЧЕСТВО(Ссылка)? Разберем этот момент подробнее:
Ссылка является первичным ключом таблицы и входит в кластерный индекс базы данных.Ссылка никогда не может быть равным NULL.COUNT(*) подсчитывает все строки, включая содержащие NULL, а COUNT(Выражение) игнорирует строки со значением NULL. Поскольку ссылка всегда заполнена, оптимизатор СУБД генерирует абсолютно идентичный план выполнения для обоих вариантов. Тем не менее общепринятым стандартом 1С для подсчета всех строк является именно КОЛИЧЕСТВО(*).Важное замечание: согласно стандартам разработки платформы 1С, категорически запрещено заменять функцию КОЛИЧЕСТВО(*) конструкцией СУММА(1). На таблицах больших объемов (от 10 млн строк) суммирование единиц вызывает ошибку арифметического переполнения из-за фиксированной разрядности промежуточных вычислений в СУБД.
Иногда требуется проверить наличие записей без составления текста запроса, оперируя исключительно менеджером справочника. В таком случае крайне не рекомендуется использовать перебор выборки в цикле. Достаточно прочитать первую запись:
Выборка = Справочники.Номенклатура.Выбрать();
СправочникПуст = НЕ Выборка.Следующий();
Если метод Следующий() вернул Ложь уже на первом шаге, значит, выборка пуста и справочник не содержит записей. Однако с точки зрения минимизации трафика и нагрузки на СУБД запрос с конструкцией ВЫБРАТЬ ПЕРВЫЕ 1 остается предпочтительным решением.
При проверке справочников важно учитывать условия реальной конфигурации, которые могут исказить итоговые цифры:
УстановитьПривилегированныйРежим(Истина).
ГДЕ
Номенклатура.Предопределенный = ЛОЖЬ
ГДЕ необходимо добавить условия ПометкаУдаления = ЛОЖЬ и ЭтоГруппа = ЛОЖЬ (для иерархических справочников).