Проблема низкой производительности 1С в связке с MSSQL на виртуальных средах часто становится камнем преткновения между системными администраторами и программистами 1С. В данной статье мы подробно разберем, как локализовать проблему, правильно настроить серверную часть и на что обратить внимание в программном коде, чтобы отчеты перестали формироваться по 20 минут.
Первым делом проанализируем ситуацию, когда аппаратные ресурсы сервера кажутся достаточными, но система работает медленно. Разберем базовые настройки VMware ESXi, которые критически важны для тяжелых СУБД:
Reserve all guest memory). Это предотвратит работу механизма ballooning, который может забирать память у SQL-сервера, вызывая катастрофические задержки.VMXNET3 и VMware Paravirtual SCSI (PVSCSI). Это минимизирует накладные расходы на виртуализацию ввода-вывода.Если в базе данных годами не проводилось обслуживание, это первая причина деградации производительности. Рассмотрим создание плана обслуживания. Проанализируем состояние индексов и статистики. Выясним, почему простое перестроение индексов может уменьшить размер бэкапа и ускорить чтение данных.
Для автоматизации процесса рекомендуется использовать скрипт, который анализирует уровень фрагментации и выбирает между REORGANIZE и REBUILD:
DECLARE @SQL NVARCHAR(MAX)
DECLARE @MIN_IND_SIZE integer = 128
DECLARE @MIN_FRAGMENTATION_LEVEL integer = 10
DECLARE @CRITICAL_FRAGMENTATION_LEVEL integer = 30
DECLARE currentIndex CURSOR LOCAL READ_ONLY FORWARD_ONLY FOR
SELECT 'ALTER INDEX [' + ind.name + N'] ON [' + SCHEMA_NAME(obj.[schema_id]) + '].[' + obj.name + '] ' +
CASE WHEN stat.avg_fragmentation_in_percent > @CRITICAL_FRAGMENTATION_LEVEL
THEN 'REBUILD WITH (SORT_IN_TEMPDB = ON, ONLINE = ON)'
ELSE 'REORGANIZE' END + ';'
FROM (
SELECT stat.[object_id], stat.index_id,
avg_fragmentation_in_percent = MAX(stat.avg_fragmentation_in_percent)
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'DETAILED') stat
WHERE stat.page_count > @MIN_IND_SIZE AND stat.index_id > 0
AND stat.avg_fragmentation_in_percent > @MIN_FRAGMENTATION_LEVEL
GROUP BY stat.[object_id], stat.index_id
) stat
JOIN sys.indexes ind ON stat.[object_id] = ind.[object_id] AND stat.index_id = ind.index_id
JOIN sys.objects obj ON obj.[object_id] = stat.[object_id]
OPEN currentIndex
FETCH NEXT FROM currentIndex INTO @SQL
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC sys.sp_executesql @SQL
FETCH NEXT FROM currentIndex INTO @SQL
END
CLOSE currentIndex
DEALLOCATE currentIndex
Важно: Помимо индексов, необходимо настроить ежедневное обновление статистики (Update Statistics). Актуальная статистика позволяет оптимизатору SQL строить верные планы запросов, что напрямую влияет на скорость формирования сложных отчетов.
Разберем специфические параметры СУБД, которые часто вызывают споры, но имеют решающее значение:
1. Это заставляет один запрос выполняться в рамках одного ядра процессора, исключая затраты на синхронизацию потоков. В некоторых случаях (при наличии очень мощных ядер и малого количества пользователей) можно пробовать значения 2 или 4, но начинать следует с 1.MAXDOP не равен 1, это значение стоит поднять до 50 или выше, чтобы SQL не пытался распараллеливать мелкие запросы.Max Server Memory в настройках SQL, оставив 4-8 ГБ для нужд ОС и сервера 1С, если он установлен на этой же машине. Это предотвратит ситуацию, когда SQL "выъедает" всю память, заставляя систему уходить в своп.TempDB на максимально быстрые диски (SSD/NVMe). Рекомендуется создать количество файлов TempDB, равное количеству логических ядер процессора (до 8 штук) одинакового размера.Если после всех настроек железа отчет "По договорам" все равно выполняется 20 минут, причина кроется в коде. Проанализируем типичные ошибки программирования в конфигурациях на обычных формах:
Запросы в цикле: Это "классика" неоптимального кода. Вместо того чтобы получить все данные одним запросом, программа в цикле 10 000 раз обращается к базе данных за информацией по каждому договору. Посмотрим на пример того, как делать НЕЛЬЗЯ:
// Плохой пример кода
Для Каждого Строка Из СписокДоговоров Цикл
Запрос = Новый Запрос("ВЫБРАТЬ Остаток ИЗ Регистр.Остатки ГДЕ Договор = &Договор");
Запрос.УстановитьПараметр("Договор", Строка.Договор);
// ... выполнение запроса
КонецЦикла;
Такой код будет работать медленно даже на суперкомпьютере. Решение — переписать отчет на использование временных таблиц и получение всех данных одним пакетом.
Управление итогами: В 1С есть механизм итогов. Если дата рассчитанных итогов (Операции - Управление итогами) сильно отстает от текущей даты, система при каждом формировании отчета будет вычислять остатки с нуля за все предыдущие периоды. Проверьте актуальность рассчитанных итогов!
Поскольку пользователи работают в режиме Толстый клиент, важно понимать, что основная нагрузка по обработке данных ложится на клиентскую машину или терминальный сервер. Рассмотрим недостатки этого подхода:
В толстом клиенте огромные объемы данных передаются от сервера к клиенту по сети для последующей обработки. Если сеть нестабильна или имеет низкую пропускную способность, это станет узким местом. Переход на Тонкий клиент и Управляемые формы позволяет перенести основные вычисления на мощный сервер, но это требует серьезной переработки конфигурации.
Подводя итог, проанализируем чек-лист для ускорения системы:
MAXDOP = 1 в настройках SQL Server.Shared Memory: если сервер 1С и SQL на одной машине, этот протокол должен быть включен и приоритетен.Только комплексный подход, сочетающий системное администрирование и аудит кода, позволит добиться комфортной работы пользователей в 1С.