В практике разработчика 1С часто возникает задача протестировать производительность алгоритмов или отчетов на больших объемах данных. Создавать в реальной или даже демонстрационной базе сотни тысяч элементов справочников — процесс долгий, трудозатратный, а последующая очистка базы может занять еще больше времени. В этой статье мы разберем эффективные методы имитации огромного количества строк в результате запроса, используя всего один реальный элемент справочника.
Самый популярный и надежный способ — это создание временной таблицы с небольшим набором цифр и последующее многократное соединение этой таблицы самой с собой. В теории баз данных это называется Cross Join (декартово произведение). Суть метода заключается в том, что при соединении двух таблиц без указания условия связи каждая строка первой таблицы соединяется с каждой строкой второй таблицы.
Давайте проанализируем, как создать базовую таблицу из 10 цифр (от 0 до 9):
ВЫБРАТЬ 0 КАК Ц ПОМЕСТИТЬ ЦЦ
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 1
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 2
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 3
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 4
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 5
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 6
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 7
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 8
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 9;
Теперь, имея таблицу ЦЦ с 10 строками, мы можем легко получить 100, 1 000 или даже 1 000 000 строк. Для получения 1 000 000 строк нам достаточно соединить эту таблицу саму с собой 6 раз (10 в 6-й степени).
Рассмотрим пример запроса для генерации 100 000 строк:
ВЫБРАТЬ
Ц1.Ц + 10 * Ц2.Ц + 100 * Ц3.Ц + 1000 * Ц4.Ц + 10000 * Ц5.Ц КАК НомерСтроки
ПОМЕСТИТЬ ВТ_Числа
ИЗ
ЦЦ КАК Ц1,
ЦЦ КАК Ц2,
ЦЦ КАК Ц3,
ЦЦ КАК Ц4,
ЦЦ КАК Ц5;
Обратите внимание, что в секции ИЗ мы просто перечисляем таблицы через запятую. Это инициирует декартово произведение. Каждое новое упоминание таблицы ЦЦ увеличивает итоговое количество строк в 10 раз.
Если нам нужно очень быстро нарастить объем данных, мы можем использовать принцип «двоичного подъема». Вместо того чтобы всегда использовать таблицу из 10 элементов, мы можем на каждом шаге создавать новую временную таблицу, соединяя предыдущую саму с собой.
Проанализируем этот алгоритм по шагам:
Таким образом, всего за 5-6 шагов (соединений) мы получаем огромный массив данных. Этот метод позволяет писать текст запроса компактнее, чем при использовании десятичной системы.
После того как мы сгенерировали временную таблицу с нужным количеством строк (например, 500 000), нам нужно «превратить» эти числа в элементы справочника. Для этого мы берем один реальный элемент (например, ссылку на товар «Конфеты») и соединяем его с нашей таблицей чисел.
Выясним, как это выглядит в итоговом запросе:
ВЫБРАТЬ
Номенклатура.Ссылка КАК Товар,
ВТ_Числа.НомерСтроки КАК ИмитацияИндекса
ИЗ
Справочник.Номенклатура КАК Номенклатура
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_Числа КАК ВТ_Числа
ПО (Номенклатура.Ссылка = &СсылкаНаЕдинственныйТовар)
В результате СУБД вернет 500 000 строк, в каждой из которых будет указана ссылка на один и тот же товар. Для системы это будет выглядеть как массив из полумиллиона записей, что идеально подходит для нагрузочного тестирования компоновки данных, заполнения коллекций или работы динамических списков.
Существует еще один «ленивый» способ. В любой современной конфигурации на базе БСП есть таблицы, которые почти всегда заполнены данными. Например, справочник ИдентификаторыОбъектовМетаданных или регистр сведений ВерсииПодсистем. Если в справочнике метаданных у вас 500 записей, то соединив его сам с собой один раз, вы получите 250 000 строк (500 * 500).
Рассмотрим пример:
ВЫБРАТЬ ПЕРВЫЕ 500000
&ЕдинственнаяСсылка КАК Ссылка
ИЗ
Справочник.ИдентификаторыОбъектовМетаданных КАК Т1
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.ИдентификаторыОбъектовМетаданных КАК Т2 ПО ИСТИНА
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.ИдентификаторыОбъектовМетаданных КАК Т3 ПО ИСТИНА
Использование конструкции ПЕРВЫЕ позволяет точно ограничить результат до нужных 500 000, даже если декартово произведение выдает миллионы строк.
При использовании таких методов имитации важно помнить о нескольких критических моментах, которые могут повлиять на стабильность сервера:
tempdb. Это потребляет дисковое пространство и оперативную память.Массив или ТаблицаЗначений, заполнить её в цикле нужным количеством строк и передать в запрос как параметр. Платформа 1С сама поместит эти данные во временную таблицу при выполнении запроса.Разберем пример передачи через таблицу значений:
ТЗ_Числа = Новый ТаблицаЗначений;
ТЗ_Числа.Колонки.Добавить("Число", Новый ОписаниеТипов("Число"));
Для Счетчик = 1 По 500000 Цикл
ТЗ_Числа.Добавить().Число = Счетчик;
КонецЦикла;
Запрос = Новый Запрос("ВЫБРАТЬ Число ПОМЕСТИТЬ ВТ_Числа ИЗ &ТЗ КАК ТЗ; ...дальнейшая работа...");
Запрос.УстановитьПараметр("ТЗ", ТЗ_Числа);
Этот способ часто работает быстрее и понятнее для других разработчиков, хотя и требует небольшого объема оперативной памяти на стороне сервера приложений 1С для формирования самой таблицы перед отправкой на SQL.
Подводя итог, можно сказать, что имитация данных в запросе — это мощный инструмент в руках разработчика. Мы рассмотрели несколько подходов: от чистого SQL-метода декартова произведения до использования встроенных объектов платформы. Выбор метода зависит от ваших конкретных задач и того, насколько «чистым» вы хотите оставить код вашего запроса.