Разработчики, работающие с платформой 1С:Предприятие 7.7, часто сталкиваются с ограничением штатного языка запросов («черных запросов»), в котором отсутствует прямой аналог SQL-команд TOP или LIMIT. Задача — найти, к примеру, последние 10 документов определенного вида или одну самую свежую запись без указания жесткого периода — становится нетривиальной. Если период поиска заранее неизвестен и может составлять как месяц, так и несколько лет, стандартный запрос начнет сканировать всю базу данных, что приведет к колоссальным задержкам.
В этой статье мы подробно разберем, как решить задачу ограничения количества выбираемых элементов, проанализируем эффективность различных подходов и выясним, почему некоторые «хитрые» способы могут только навредить производительности.
Проанализируем самый эффективный и профессиональный способ решения задачи. Если ваша база данных работает на MS SQL Server, использование внешней компоненты 1С++ позволяет писать запросы на чистом SQL. Это снимает все ограничения встроенного языка 1С 7.7.
Разберем основные преимущества этого метода:
SELECT TOP 10.Рассмотрим пример кода для получения последних 5 документов поступления:
// Создаем объект для работы с SQL
ЗапросSQL = СоздатьОбъект("ODBCRecordset");
ТекстЗапроса = "
|SELECT TOP 5
| Журнал.IDDoc as [Док $Документ],
| Журнал.IDDocDef as Док_вид
|FROM
| _1SJOURN as Журнал
|WHERE
| Журнал.IDDocDef = $ВидДокумента.ПоступлениеТоваров
|ORDER BY
| Журнал.Date_Time_IDDoc DESC
|";
ТаблицаРезультатов = ЗапросSQL.ВыполнитьИнструкцию(ТекстЗапроса);
Этот метод позволяет избежать перебора всех записей, так как SQL-сервер просто берет первые 5 строк из соответствующего индекса журнала документов.
Если использование внешних компонент невозможно или база работает в файловом режиме (DBF), следует отказаться от языка запросов в пользу объектной модели. Метод ВыбратьДокументы работает гораздо быстрее «черного» запроса в задачах поиска единичных записей, так как он использует штатные индексы и читает записи последовательно.
Разберем, как реализовать обратный поиск по шагам:
Прервать при достижении нужного количества.Посмотрим на пример реализации:
Док = СоздатьОбъект("Документ.ПоступлениеТоваров");
// Параметры: ДатаНач, ДатаКон, ОбратныйПорядок(1)
Док.ВыбратьДокументы(,, 1);
Счетчик = 0;
КоличествоНужных = 10;
Пока Док.ПолучитьДокумент() = 1 Цикл
// Здесь можно добавить дополнительные условия фильтрации
Счетчик = Счетчик + 1;
Сообщить("Найден документ: " + Док.ТекущийДокумент());
Если Счетчик >= КоличествоНужных Тогда
Прервать; // Выходим, как только набрали нужное количество
КонецЕсли;
КонецЦикла;
Важный момент: использование параметра 1 в методе ВыбратьДокументы заставляет систему идти от конца журнала к началу. Это позволяет мгновенно найти самые свежие записи даже в огромной базе без указания периода.
В обсуждениях часто всплывает идея использовать пользовательскую функцию в условии запроса. Суть заключается в том, чтобы создать глобальную переменную-счетчик и проверять ее в тексте запроса. Однако, проанализируем ситуацию глубже: этот метод не экономит ресурсы системы.
Выясним причину: даже если функция вернет «0» (Ложь) после 10-й записи, движок 1С 7.7 продолжит сканировать таблицу до конца периода (или до конца времен, если период не задан). Каждая запись в базе данных все равно будет проверена на соответствие условию, что делает этот подход крайне медленным на больших объемах данных.
Тем не менее, для небольших справочников структура может выглядеть так:
Переменная Счетчик = 0;
Функция ОграничитьВыборку()
Счетчик = Счетчик + 1;
Если Счетчик <= 10 Тогда
Возврат 1;
Иначе
Возврат 0;
КонецЕсли;
КонецФункции
// В тексте запроса
|Условие(ОграничитьВыборку() = 1);
Вердикт: использовать только для маленьких таблиц, где производительность не критична.
Если ваша задача — найти последнее значение цены, курса валюты или любого другого периодического реквизита, не используйте запросы. Для этого в 1С 7.7 существует специализированный объект Периодический.
Посмотрим на алгоритм работы:
Периодический.ИспользоватьОбъект для привязки к реквизиту справочника.ВыбратьЗначения с флагом обратного порядка.Этот метод работает моментально, так как обращается напрямую к таблице истории значений (_1SCONST) по индексу.
Если вам нужно выполнить быстрый запрос SELECT TOP, но вы не можете устанавливать ВК 1С++, можно воспользоваться стандартными средствами Windows — ADO. Этот метод позволяет подключиться к базе данных 1С (как к SQL, так и к DBF через провайдер Jet или VFPOLEDB) и выполнить произвольный запрос.
Рассмотрим особенности:
SELECT TOP N.DH123.Выбор метода зависит от ваших технических возможностей и версии базы данных:
ВыбратьДокументы или ВыбратьЭлементы с принудительным Прервать. Работает везде и достаточно быстро при наличии индексов.Периодический для поиска цен и курсов.Помните, что в 1С 7.7 отсутствие периода в «черном» запросе — это всегда риск Full Scan. Всегда старайтесь ограничивать выборку либо на уровне SQL-сервера, либо через последовательное чтение объектов с выходом из цикла.