В процессе сопровождения и аудита информационных баз 1С часто возникает задача оценить объем накопленных данных. Одной из ключевых метрик является количество документов каждого вида. Это необходимо для понимания динамики роста базы, поиска «мусорных» объектов или подготовки к свертке данных. В рамках данной статьи мы подробно разберем несколько способов получения этой информации: от универсальных запросов на встроенном языке 1С до прямых запросов к СУБД MS SQL.
Поскольку в языке запросов 1С нельзя обратиться к «виртуальной» таблице всех документов сразу, нам необходимо программно сформировать текст запроса, объединяющий данные из всех существующих таблиц документов в конфигурации. Рассмотрим наиболее эффективный подход, использующий конструкцию ОБЪЕДИНИТЬ ВСЕ.
Давайте проанализируем код, который обходит коллекцию метаданных и собирает итоговый текст запроса:
Функция ПолучитьСтатистикуПоДокументам()
Запрос = Новый Запрос;
ТекстЗапроса = "";
ПервыйДокумент = Истина;
Для Каждого МетаданныеДокумента Из Метаданные.Документы Цикл
ИмяДокумента = МетаданныеДокумента.Имя;
Представление = МетаданныеДокумента.Синоним;
Если ПустаяСтрока(Представление) Тогда
Представление = ИмяДокумента;
КонецЕсли;
ШаблонЗапроса =
"ВЫБРАТЬ
| &ИмяДокумента КАК ВидДокумента,
| &Синоним КАК Представление,
| КОЛИЧЕСТВО(*) КАК Количество
|ИЗ
| Документ." + ИмяДокумента + " КАК Таблица";
Если Не ПервыйДокумент Тогда
ТекстЗапроса = ТекстЗапроса + "
|ОБЪЕДИНИТЬ ВСЕ
|";
КонецЕсли;
ТекстЗапроса = ТекстЗапроса + СтрЗаменить(СтрЗаменить(ШаблонЗапроса, "&ИмяДокумента", """" + ИмяДокумента + """"), "&Синоним", """" + Представление + """");
ПервыйДокумент = Ложь;
КонецЦикла;
Запрос.Текст = ТекстЗапроса + "
|УПОРЯДОЧИТЬ ПО
| Количество УБЫВ";
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
Важные замечания к этому способу:
ОБЪЕДИНИТЬ ВСЕ может вызвать ошибку переполнения стека парсера SQL-сервера или превысить лимит на количество таблиц в запросе. В таких случаях мы рекомендуем разбивать выполнение на пакеты (например, по 50 документов) и объединять результаты в одну ТаблицаЗначений.ГДЕ ПометкаУдаления = ЛОЖЬ.Если вам не нужен один общий результат для сортировки, а достаточно просто вывести список в консоль или лог, можно использовать объект ВыборкаИзРезультатаЗапроса внутри цикла. Этот метод менее требователен к памяти сервера 1С, так как не формирует гигантскую строку текста запроса.
Для Каждого ДокМета Из Метаданные.Документы Цикл
ТекстЗапроса = "ВЫБРАТЬ КОЛИЧЕСТВО(*) КАК Кол ИЗ Документ." + ДокМета.Имя;
Запрос = Новый Запрос(ТекстЗапроса);
Результат = Запрос.Выполнить().Выбрать();
Если Результат.Следующий() Тогда
Сообщить(ДокМета.Имя + ": " + Результат.Кол);
КонецЕсли;
КонецЦикла;
Проанализируем этот подход: он считается «плохой практикой» (запрос в цикле), однако в административных задачах он вполне допустим, так как позволяет избежать проблем с длиной текста запроса в очень больших конфигурациях.
Для системных администраторов и разработчиков, имеющих доступ к консоли MS SQL Server Management Studio, существует способ мгновенного получения статистики. Этот метод работает на порядки быстрее, так как обращается к системным таблицам, хранящим количество строк в партициях таблиц.
Рассмотрим пример запроса, который выбирает данные из sys.partitions. Обратите внимание, что в 1С таблицы документов начинаются с префикса _Document.
SELECT
t.name AS [TableName],
p.rows AS [RowCount]
FROM
sys.tables AS t
INNER JOIN
sys.partitions AS p ON t.object_id = p.object_id
WHERE
t.name LIKE '_Document%'
AND p.index_id IN (0, 1) -- 0: heap, 1: clustered index
ORDER BY
p.rows DESC;
Нюансы использования SQL:
sys.partitions могут быть не на 100% точными в реальном времени, если статистика базы данных давно не обновлялась. Однако для общей оценки объема этого более чем достаточно._Document123. Чтобы понять, какому объекту 1С соответствует номер 123, используйте функцию ПолучитьСтруктуруХраненияБазыДанных() в 1С или загляните в таблицу DBSchema.SELECT COUNT(*) к реальным таблицам данных всегда добавляйте подсказку WITH (NOLOCK), чтобы не заблокировать работу пользователей в активной базе.Выясним, какой метод лучше выбрать в зависимости от ситуации:
ОБЪЕДИНИТЬ ВСЕ. Это дает возможность легко вывести результат в ТабличныйДокумент или на диаграмму.Рассмотрим ситуацию с использованием PostgreSQL. Если ваша база работает под управлением этой СУБД, запрос к системным таблицам будет выглядеть иначе. Мы можем использовать таблицу pg_class, чтобы получить примерное количество строк (reltuples):
SELECT
relname AS table_name,
reltuples AS row_count
FROM
pg_class
WHERE
relname LIKE '_document%'
ORDER BY
reltuples DESC;
В заключение отметим, что при работе с любым из этих методов важно помнить о регламентных операциях. Если в базе давно не выполнялось обновление статистики или очистка процедурного кэша, результаты (особенно SQL-методов) могут искажаться. Регулярный мониторинг количества документов поможет вам вовремя заметить аномальный рост базы и принять меры по ее оптимизации.