При работе с крупными базами данных в связке 1С:Предприятие и MS SQL Server администраторы и разработчики часто сталкиваются с критической ошибкой: «Недостаточно памяти для получения результата запроса к базе данных». Эта ситуация особенно характерна для тяжелых регламентных заданий, ночных расчетов или формирования масштабных аналитических отчетов. Рассмотрим природу этой проблемы, разберем типичные заблуждения и выработаем комплексный алгоритм решения.
Первое и самое важное правило при диагностике данной ошибки: в 99% случаев виновником является не MS SQL Server, а рабочий процесс сервера 1С — rphost. Распространен миф о том, что если SQL Server «забрал» всю доступную оперативную память, то запросу 1С некуда «расти». На самом деле механизмы работы этих систем сильно различаются.
Проанализируем ситуацию: когда SQL Server выполняет запрос, он использует свою память (Buffer Pool) для кэширования данных и Workspace Memory для операций сортировки и группировки. Но как только данные подготовлены, SQL Server начинает передавать их «потоком» клиенту, в данном случае — серверу 1С. Именно процесс rphost должен принять этот объем данных, сформировать из них объект РезультатЗапроса и удерживать его в своей оперативной памяти для дальнейшей обработки программным кодом.
Если результат запроса содержит миллионы строк или десятки гигабайт данных, rphost пытается выделить соответствующий объем в своем адресном пространстве. Если физическая память сервера исчерпана или установлены жесткие лимиты в консоли администрирования кластера 1С, возникает искомая ошибка. При этом сам SQL Server может чувствовать себя прекрасно, так как он лишь «отдает» данные.
Если сервер 1С и сервер баз данных установлены на одной физической машине, они вступают в жесткую конкуренцию за ресурсы. SQL Server по умолчанию настроен так, чтобы занимать всю доступную память, которую ему отдает ОС. Это необходимо для кэширования, но пагубно для rphost, которому тоже нужно место для обработки результатов запросов.
Разберем, как правильно ограничить аппетиты SQL Server, чтобы оставить «воздух» для процессов 1С:
Важная рекомендация: Оставляйте для нужд операционной системы и рабочих процессов 1С не менее 20–30% общего объема оперативной памяти сервера. Например, если на сервере 128 ГБ ОЗУ, выделите сиквелу не более 80–90 ГБ. Это позволит rphost стабильно работать с тяжелыми выборками без принудительного сброса данных в файл подкачки.
В современных версиях платформы (8.3.15 и выше) появились механизмы защиты от «прожорливых» запросов. Проанализируем настройки в Консоли администрирования кластера 1С, которые могут вызывать преждевременное прерывание запроса:
rphost превысит этот порог, кластер начнет их перезапускать. Если для выполнения вашего задания требуется 50 ГБ, а лимит стоит 40 ГБ — вы получите ошибку.Посмотрим на пример настройки: если вы понимаете, что регламентное задание легитимно обрабатывает огромный массив данных, временно установите эти значения в 0 (без ограничений) для проверки гипотезы, либо увеличьте их до разумных пределов, соответствующих вашему «железу».
Чтобы точно понять, какой именно запрос вызывает падение, необходимо настроить Технологический журнал (ТЖ). Нам интересны события MEM (мониторинг памяти) и EXCP (исключения). Рассмотрим пример настройки logcfg.xml для отлова проблем с памятью:
<config xmlns="http://v8.1c.ru/7.4/get/logcfg">
<log location="C:\LOGS\MEMORY" history="24">
<event>
<eq property="Name" value="MEM"/>
</event>
<event>
<eq property="Name" value="EXCP"/>
<like property="Descr" value=".*Недостаточно памяти.*"/>
</event>
<property name="All"/>
</log>
</config>
Анализ логов позволит увидеть «скачок» потребления памяти конкретным сеансом непосредственно перед возникновением ошибки. Это поможет локализовать конкретную строчку кода в модуле регламентного задания.
Если настройки серверов верны, но ошибка сохраняется, значит, проблема в архитектуре самого запроса. Проанализируем ситуацию с временными таблицами. Часто разработчики забывают, что хотя временные таблицы хранятся в tempdb на диске (или в памяти SQL), финальная выборка из них все равно попадает в rphost. Для автоматической очистки неиспользуемых таблиц в коде можно применить обработку для оптимизации временных таблиц в пакетных запросах.
Выясним основные способы оптимизации кода 1С:
rphost своевременно освобождаться.LEFT JOIN). Постарайтесь типизировать данные до помещения во временную таблицу.МенеджерВременныхТаблиц.Закрыть() сразу после того, как таблицы стали не нужны. Хотя это больше влияет на tempdb, косвенно это снижает нагрузку на общую шину данных.СГРУППИРОВАТЬ ПО и агрегатные функции в самом запросе. Старайтесь возвращать в 1С уже «свернутый» результат, а не детальные записи, которые вы потом планируете обходить в цикле и суммировать вручную.Иногда запрос «подвисает» или падает из-за того, что SQL Server не может выделить ему квант памяти для выполнения (Memory Grant). Это происходит, если одновременно запущено много тяжелых процессов. Чтобы увидеть такие запросы, выполните следующий системный запрос в SSMS:
SELECT
request_id,
session_id,
requested_memory_kb / 1024 as RequestedMB,
granted_memory_kb / 1024 as GrantedMB,
wait_time_ms
FROM sys.dm_exec_query_memory_grants
WHERE granted_memory_kb IS NULL OR wait_time_ms > 0
Если вы видите здесь записи, значит, ваши регламентные задания буквально «дерутся» за память внутри SQL Server. В этом случае поможет разнесение заданий по времени или увеличение параметра Max Degree of Parallelism (MAXDOP), чтобы один запрос не захватывал все ресурсы процессора и памяти одновременно. Для удобного исследования текущих запросов и ожиданий на стороне СУБД можно использовать инструмент для анализа SQL-сервера и блокировок из 1С.
Подведем итог: решение проблемы «Недостаточно памяти» всегда комплексно. Мы должны ограничить SQL Server, чтобы он не подавлял rphost, настроить лимиты в кластере 1С под реальные задачи и переписать тяжелые запросы, внедрив порционную загрузку данных. Только согласованная работа всех уровней системы обеспечит стабильность при обработке больших массивов информации.