При работе в конфигурациях на платформе 1С:Предприятие 8.3 пользователи нередко сталкиваются с аварийным завершением операций и ошибкой: Ошибка выполнения запроса: Недостаточно памяти для получения результата запроса к базе данных. Чаще всего сбой проявляется в процессе подбора номенклатуры, при проведении тяжелых документов или формировании нетиповых отчетов. Разберем детально физику возникновения этой проблемы, проанализируем распределение ресурсов между сервером СУБД и сервером 1С, а также пошагово выполним системные и программные настройки для полного устранения сбоя.
Для эффективной локализации проблемы выясним, на каком именно уровне инфраструктуры происходит исчерпание памяти. В архитектуре клиент-серверной работы 1С задействованы три ключевых звена: клиентское приложение (толстый или тонкий клиент), кластер серверов 1С (процессы rphost, rmngr) и сервер реляционной СУБД (например, Microsoft SQL Server или PostgreSQL).
Рассмотрим основные факторы, приводящие к ошибке:
Запрос.Выполнить() выполняется непосредственно в адресном пространстве процесса 1cv8.exe на компьютере пользователя. Для 32-битных процессов Windows накладывает жесткое ограничение в 2 ГБ виртуального адресного пространства. При наличии фрагментации оперативной памяти сбой возникает уже при выделении 1.2–1.6 ГБ, даже если физически на рабочей станции установлено 8 или 16 ГБ ОЗУ.Buffer Pool). Если SQL Server и сервер 1С установлены на одной машине с 32 ГБ ОЗУ, СУБД может занять 28–30 ГБ, оставив процессам rphost и операционной системе считаные мегабайты, что провоцирует системный дефицит ресурсов.Cardinality Estimator) может генерировать неэффективные планы запросов для структур 1С, вызывая раздувание промежуточных результатов в базе tempdb и чрезмерный расход памяти.Если сбой происходит на рабочих местах пользователей в конфигурациях с обычными формами (толстый клиент), наиболее быстрым и действенным способом решения проблемы является установка 64-разрядного клиента платформы 1С.
Разберем по шагам порядок действий:
8.3.10.2639 или старше).C:\Program Files\1cv8\ (в отличие от 32-битной версии, которая устанавливается в C:\Program Files (x86)\1cv8\).1cv8.exe сможет адресовать весь объем оперативной памяти рабочей станции и использовать файл подкачки без ограничений в 2 ГБ.Проанализируем конфигурацию сервера, если сервер приложений 1С и СУБД Microsoft SQL Server установлены совместно на одном физическом или виртуальном сервере (например, с общим объемом памяти 32 ГБ).
Рассчитаем оптимальное распределение памяти:
ragent, rmngr, rphost): 8–10 ГБ.Для ограничения аппетитов СУБД выполним настройку через среду SQL Server Management Studio (SSMS):
Object Explorer) нажмем правой кнопкой мыши на имени сервера и выберем пункт Свойства (Properties).16384, для 18 ГБ — 18432.0).При переносе баз 1С на современные выпуски MS SQL Server (2014, 2016, 2017, 2019) важно адаптировать параметры СУБД, чтобы исключить деградацию планов выполнения запросов.
Выполним следующие оптимизационные команды в окне нового запроса SSMS:
-- 1. Включаем классический оптимизатор планов запросов для базы 1С
USE [Имя_Базы_1С];
GO
ALTER DATABASE SCOPED CONFIGURATION SET LEGACY_CARDINALITY_ESTIMATION = ON;
GO
-- 2. Ограничиваем параллелизм выполнения тяжелых запросов
EXEC sys.sp_configure N'show advanced options', N'1' RECONFIGURE WITH OVERRIDE;
GO
EXEC sys.sp_configure N'max degree of parallelism', N'1';
GO
RECONFIGURE WITH OVERRIDE;
GO
Параметр LEGACY_CARDINALITY_ESTIMATION = ON возвращает алгоритм оценки кардинальности к проверенной логике SQL Server 2012, предотвращая раздувание промежуточных выборок при работе с временными таблицами 1С. Параметр max degree of parallelism = 1 исключает паразитные взаимные блокировки при параллельном расчете запросов на многоядерных процессорах.
Рассмотрим структуру кода, на котором происходит падение. В модулях подбора номенклатуры (например, Обработка.ПодборНоменклатуры) типовая ошибка заключается в формировании запроса к остаткам без жестких условий в параметрах виртуальной таблицы.
Посмотрим на классический неоптимальный пример, вызывающий переполнение памяти:
// НЕОПТИМАЛЬНЫЙ ВАРИАНТ:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Номенклатура,
| Номенклатура.Код КАК Код,
| Номенклатура.Наименование КАК Наименование,
| ЕСТЬNULL(ТоварыНаСкладахОстатки.КоличествоОстаток, 0) КАК Остаток
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, ) КАК ТоварыНаСкладахОстатки
| ПО Номенклатура.Ссылка = ТоварыНаСкладахОстатки.Номенклатура
|ГДЕ
| Номенклатура.ЭтоГруппа = ЛОЖЬ";
РезультатЗапроса = Запрос.Выполнить(); // Падение по нехватке памяти при выгрузке
В приведенном фрагменте виртуальная таблица ТоварыНаСкладах.Остатки рассчитывает остатки абсолютно по всей номенклатуре и по всем складам компании, после чего СУБД пытается передать всю эту таблицу в оперативную память клиента.
Перепишем запрос оптимально, добавив передачу условий непосредственно в параметры виртуальной таблицы и наложив фильтрацию по выбранной группе справочника или конкретному складу:
// ОПТИМИЗИРОВАННЫЙ ВАРИАНТ:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Номенклатура,
| Номенклатура.Артикул КАК Артикул,
| Номенклатура.Код КАК Код,
| Номенклатура.Наименование КАК Наименование,
| ЕСТЬNULL(ТоварыОстатки.ВНаличииОстаток, 0) КАК Остаток
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(
| &Период,
| Склад = &ТекущийСклад И Номенклатура В ИЕРАРХИИ (&РодительНоменклатуры)
| ) КАК ТоварыОстатки
| ПО Номенклатура.Ссылка = ТоварыОстатки.Номенклатура
|ГДЕ
| Номенклатура.ВАрхиве = ЛОЖЬ
| И Номенклатура.ЭтоГруппа = ЛОЖЬ
| И Номенклатура.Ссылка В ИЕРАРХИИ(&РодительНоменклатуры)";
Запрос.УстановитьПараметр("Период", ТекущаяДата());
Запрос.УстановитьПараметр("ТекущийСклад", СкладДокумента);
Запрос.УстановитьПараметр("РодительНоменклатуры", ВыбраннаяПапкаНоменклатуры);
РезультатЗапроса = Запрос.Выполнить();
Разберем ключевые правила оптимизации запросов выборки:
Остатки() или СрезПоследних(). Это позволяет СУБД отфильтровать записи на этапе чтения индексов, не сканируя весь регистр.ДинамическийСписок с включенным свойством ДинамическоеСчитываниеДанных. В обычных формах при больших объемах справочников целесообразно использовать механизм постраничного чтения данных с оператором ПЕРВЫЕ N.Если ошибка возникает эпизодически при проведении документов за старые периоды, причиной могут быть неактуальные рассчитанные итоги регистров накопления и бухгалтерии.
Выполним регламентные процедуры обслуживания базы данных 1С:
%LocalAppData%\1C\1Cv8\ и %AppData%\1C\1Cv8\ (папки с буквенно-цифровыми GUID-именами).Комплексное применение указанных мер — установка 64-битного клиента для преодоления лимита 2 ГБ, фиксация памяти MS SQL Server, включение Legacy Cardinality Estimation и наложение параметров в виртуальных таблицах запросов — полностью ликвидирует ошибку нехватки памяти и существенно ускоряет отклик базы данных.