Настройка SQL Server для 1С: 10 параметров, которые нужно проверить первым делом

По статистике 1С, около 60% обращений по производительности в клиент-серверном варианте связаны не с кодом конфигурации, а с настройкой SQL Server. Ставим систему, запускаем базу, работаем. Через полгода приходит бухгалтерия: «Закрытие месяца идёт четвёртый час». Подключаемся, смотрим — и первое, что видим: SQL Server с дефолтными настройками.

За последние несколько лет мы проверили десятки серверов. Почти на каждом хотя бы три из десяти параметров стояли не так. Ниже — конкретный чек-лист. Без теории, без «зависит от ситуации». Только значения, которые работают для 1С.

Сравнение типичных и рекомендуемых настроек SQL Server для 1С

1. MAXDOP = 1

Это первое, что нужно проверить. MAXDOP (Maximum Degree of Parallelism) по умолчанию стоит 0 — SQL Server сам решает, сколько ядер использовать для одного запроса. Для OLTP-нагрузки 1С это убийственно.

Платформа 1С генерирует множество коротких запросов. Когда SQL Server начинает параллелить короткий запрос на 8 ядер, накладные расходы на координацию потоков превышают пользу. Добавьте сюда CXPACKET-ожидания — и вот уже 200 пользователей стоят в очереди, хотя процессор загружен на 30%.

Ставим MAXDOP = 1. Без вариантов. Если у вас аналитические запросы (OLAP), вынесите их на отдельный экземпляр.

EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'max degree of parallelism', 1;
RECONFIGURE;

2. Cost Threshold for Parallelism = 50

Работает в паре с MAXDOP. Даже если вы поставили MAXDOP = 1, стоит подстраховаться: Cost Threshold определяет, при какой «стоимости» запрос вообще рассматривается для параллельного выполнения. Дефолтное значение 5 — абсурдно низкое. Практически любой запрос попадает под параллелизм.

Ставим 50. Для 1С этого хватает с запасом.

EXEC sp_configure 'cost threshold for parallelism', 50;
RECONFIGURE;

3. Max Server Memory

SQL Server по умолчанию забирает всю доступную оперативную память. Всю. Операционной системе, кластеру 1С, антивирусу — ничего не остаётся. Начинается подкачка, и производительность падает в разы.

Формула простая: оставьте операционной системе 7-8 ГБ. Если на сервере 64 ГБ — ставьте Max Server Memory = 56 ГБ. Если 32 ГБ — ставьте 24 ГБ.

-- Для сервера с 64 ГБ RAM
EXEC sp_configure 'max server memory (MB)', 57344; -- 56 GB
RECONFIGURE;

На практике мы видели сервер с 128 ГБ, где SQL Server занимал 127 ГБ. Кластер 1С едва шевелился. После ограничения памяти до 112 ГБ время отклика сократилось вдвое — и это без единого изменения в коде.

4. TempDB — минимум 4 файла

TempDB — рабочая область SQL Server. Временные таблицы, сортировки, перестроения индексов — всё проходит через неё. По умолчанию TempDB — один файл. Один файл на все потоки. Очередь на запись растёт, и вы видите ожидания PAGELATCH.

Рекомендуемая конфигурация TempDB для 1С

Правило: количество файлов TempDB = количество логических ядер процессора, но не больше 8. Если ядер 4 — ставьте 4 файла. Если 16 — ставьте 8. Все файлы должны быть одного размера, иначе SQL Server будет перекашивать нагрузку.

Начальный размер каждого файла — 1024 МБ. Autogrow — 512 МБ (фиксированный). Лог-файл — один, 512 МБ.

5. Autogrow: фиксированный, не процентный

Процентный autogrow — бомба замедленного действия. При базе 100 МБ рост на 10% — это 10 МБ, нормально. При базе 200 ГБ рост на 10% — это 20 ГБ за одну операцию. Сервер замирает на минуту, пока аллоцирует и инициализирует 20 ГБ на диске. Все пользователи ждут.

Для файлов данных ставим autogrow = 1024 МБ. Для файлов журнала транзакций — 512 МБ. Фиксированный, в мегабайтах.

ALTER DATABASE [your_1c_db]
MODIFY FILE (NAME = your_1c_db_data, FILEGROWTH = 1024MB);

ALTER DATABASE [your_1c_db]
MODIFY FILE (NAME = your_1c_db_log, FILEGROWTH = 512MB);

Важный нюанс: если у вас включён Instant File Initialization (о нём ниже), рост файлов данных происходит почти мгновенно. Но для файлов журнала он не работает — там всегда нулевая инициализация. Поэтому для журнала фиксированный autogrow особенно критичен.

6. AUTO_SHRINK = OFF

AUTO_SHRINK — параметр, который кажется полезным: база автоматически сжимается, освобождает место. На деле это катастрофа. SQL Server сжимает файл данных, фрагментируя все индексы. Потом база растёт обратно (потому что данные-то никуда не делись). И так по кругу: сжатие → фрагментация → рост → сжатие.

Мы видели базу, где AUTO_SHRINK был включён три года. Фрагментация индексов — 99%. Перестроение индексов по расписанию не помогало: AUTO_SHRINK сводил всё к нулю за сутки.

ALTER DATABASE [your_1c_db] SET AUTO_SHRINK OFF;

Если нужно освободить место — делайте это вручную, планово, с последующим перестроением индексов.

7. AUTO_UPDATE_STATISTICS_ASYNC = ON

Когда SQL Server обнаруживает, что статистика устарела, он останавливает выполнение запроса и пересчитывает её. Пользователь ждёт. При синхронном обновлении один невезучий запрос может зависнуть на секунды, пока статистика обновляется на большой таблице.

С асинхронным обновлением текущий запрос выполняется со старой (но всё ещё приемлемой) статистикой, а обновление происходит в фоне. Следующие запросы уже получат свежие данные.

ALTER DATABASE [your_1c_db] SET AUTO_UPDATE_STATISTICS_ASYNC ON;

8. Query Store — включить обязательно

Query Store — это чёрный ящик для запросов. SQL Server сохраняет планы выполнения и статистику каждого запроса. Когда через месяц приходят с вопросом «почему вчера всё тормозило с 14:00 до 16:00?», Query Store покажет, какие запросы деградировали и почему.

Рекомендуемые параметры Query Store для 1С

Без Query Store расследование инцидента — это гадание. С ним — конкретные цифры: план запроса, время выполнения, количество чтений.

ALTER DATABASE [your_1c_db] SET QUERY_STORE = ON (
    MAX_STORAGE_SIZE_MB = 1024,
    STALE_QUERY_THRESHOLD_DAYS = 30,
    INTERVAL_LENGTH_MINUTES = 60,
    QUERY_CAPTURE_MODE = AUTO
);

MAX_STORAGE — 1024 МБ хватает для большинства баз. STALE_QUERY — 30 дней, чтобы можно было сравнить с прошлым месяцем. INTERVAL — 60 минут, оптимальный баланс между точностью и объёмом данных.

9. Instant File Initialization

Когда SQL Server создаёт или расширяет файл данных, он по умолчанию заполняет выделенное пространство нулями. На дисках HDD (а они всё ещё встречаются) инициализация файла на 10 ГБ может занять минуту. В это время база недоступна.

Instant File Initialization позволяет пропустить нулевую инициализацию. Файл аллоцируется мгновенно. Включается на уровне ОС: учётной записи SQL Server нужно дать привилегию Perform volume maintenance tasks (SE_MANAGE_VOLUME_NAME).

Проверить, включена ли:

SELECT servicename, instant_file_initialization_enabled
FROM sys.dm_server_services
WHERE servicename LIKE 'SQL Server%';

Если instant_file_initialization_enabled = N, зайдите в Local Security Policy → User Rights Assignment → Perform volume maintenance tasks и добавьте учётную запись SQL Server. После этого перезапустите службу SQL.

10. Регламенты: индексы, статистика, CHECKDB

Настроить параметры — половина дела. Без регулярного обслуживания база деградирует.

Минимальный план обслуживания через SQL Agent:

  • Ежедневно: UPDATE STATISTICS для всех таблиц. Время выполнения — обычно 5-15 минут на базе до 100 ГБ
  • Еженедельно (воскресенье): REORGANIZE индексов с фрагментацией 10-30%, REBUILD для >30%. Занимает от 30 минут до нескольких часов в зависимости от объёма
  • Еженедельно (суббота): DBCC CHECKDB — проверка целостности базы. Единственный способ обнаружить повреждение данных до того, как станет поздно
  • Бэкапы: FULL ежедневно ночью, DIFF каждые 4-6 часов, LOG каждые 15-30 минут (если Recovery Model = Full)

Проверить текущую фрагментацию:

SELECT 
    OBJECT_NAME(ips.object_id) AS TableName,
    i.name AS IndexName,
    ips.avg_fragmentation_in_percent,
    ips.page_count
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'LIMITED') ips
JOIN sys.indexes i ON ips.object_id = i.object_id AND ips.index_id = i.index_id
WHERE ips.avg_fragmentation_in_percent > 10 AND ips.page_count > 1000
ORDER BY ips.avg_fragmentation_in_percent DESC;

Бонус: Lock Pages in Memory

Ещё один параметр, о котором часто забывают. По умолчанию Windows может выгружать страницы памяти SQL Server в файл подкачки, даже если Max Server Memory настроен правильно. При высокой нагрузке на память ОС начинает вытеснять данные SQL Server на диск — и запросы, которые должны читать из кэша, вынуждены ждать чтения с диска.

Lock Pages in Memory — привилегия Windows, которая запрещает ОС выгружать память SQL Server в pagefile. Включается аналогично Instant File Initialization: Local Security Policy → User Rights Assignment → Lock pages in memory → добавить учётную запись SQL Server.

Проверить, используется ли Lock Pages in Memory:

SELECT sql_memory_model_desc FROM sys.dm_os_sys_info;
-- CONVENTIONAL = не используется
-- LOCK_PAGES = используется

На серверах с 64+ ГБ RAM мы рекомендуем включать Lock Pages в обязательном порядке. На сервере с 32 ГБ эффект менее заметен, но тоже есть. Особенно проявляется при работе с крупными базами, когда SQL Server активно кэширует данные в buffer pool.

Типичная ситуация из практики: сервер с 64 ГБ RAM, Max Server Memory = 56 ГБ. Всё настроено, но периодически возникают «провалы» производительности длительностью 30-60 секунд. Мониторинг показывает скачки Page Life Expectancy — SQL Server теряет кэш. Причина: антивирус или служба бэкапов потребляет память, ОС вытесняет страницы SQL Server. После включения Lock Pages in Memory — провалы исчезли.

Топ ожиданий: быстрая диагностика

Настроили все параметры, но хотите убедиться, что ничего не упустили? Запросите топ ожиданий SQL Server — это моментальный снимок того, на что тратит время сервер:

SELECT TOP 10
    wait_type,
    wait_time_ms / 1000 AS wait_sec,
    signal_wait_time_ms / 1000 AS signal_sec,
    waiting_tasks_count
FROM sys.dm_os_wait_stats
WHERE wait_type NOT IN (
    'SLEEP_TASK', 'BROKER_TASK_STOP', 'SQLTRACE_BUFFER_FLUSH',
    'CLR_AUTO_EVENT', 'CLR_MANUAL_EVENT', 'LAZYWRITER_SLEEP',
    'BROKER_EVENTHANDLER', 'BROKER_RECEIVE_WAITFOR', 'FT_IFTS_SCHEDULER_IDLE_WAIT',
    'XE_DISPATCHER_WAIT', 'XE_TIMER_EVENT', 'CHECKPOINT_QUEUE',
    'WAITFOR', 'HADR_FILESTREAM_IOMGR_IOCOMPLETION', 'SP_SERVER_DIAGNOSTICS_SLEEP'
)
ORDER BY wait_time_ms DESC;

Что искать в результатах:

  • CXPACKET — параллелизм. Значит MAXDOP не = 1 или Cost Threshold слишком низкий
  • PAGELATCH_* — контенция в TempDB. Мало файлов TempDB
  • PAGEIOLATCH_* — чтение с диска. Либо мало памяти, либо диски медленные
  • LCK_M_* — блокировки. Проблема в коде 1С, не в настройках SQL
  • WRITELOG — медленная запись в журнал транзакций. Перенесите лог-файл на отдельный SSD

Один этот запрос может указать на проблему, которую вы пропустили при настройке. Рекомендуем снимать топ ожиданий раз в неделю и сравнивать — это покажет, как меняется профиль нагрузки.

Как проверить всё за 5 минут

Один скрипт — и вы видите текущее состояние всех десяти параметров:

-- MAXDOP
EXEC sp_configure 'max degree of parallelism';
-- Cost Threshold
EXEC sp_configure 'cost threshold for parallelism';
-- Memory
EXEC sp_configure 'max server memory (MB)';
-- Auto-settings
SELECT 
    name,
    is_auto_shrink_on,
    is_auto_update_stats_async_on,
    is_query_store_on
FROM sys.databases WHERE name = 'your_1c_db';
-- TempDB files
SELECT name, size/128 AS size_mb, growth/128 AS growth_mb,
       CASE WHEN is_percent_growth = 1 THEN 'PERCENT' ELSE 'MB' END AS growth_type
FROM tempdb.sys.database_files;

Скопируйте, подставьте имя базы, выполните в SSMS. Через 5 минут у вас полная картина.

Мы прогоняем этот чек-лист на каждом новом проекте. В 8 случаях из 10 находим минимум 3 параметра, требующих коррекции. Иногда одно только исправление MAXDOP убирает жалобы пользователей. Не всегда нужно лезть в код — иногда достаточно правильно настроить инфраструктуру.