Перевод базы данных 1С 7.7 с файлового режима (DBF) на MS SQL Server нередко приводит к неожиданному эффекту: отчёты и проведение документов начинают работать в несколько раз медленнее. В файловом режиме индексы и таблицы активно кэшируются в оперативной памяти клиентской станции или терминального сервера, а выборка выполняется напрямую. В случае с SQL Server стандартный движок 1С 7.7 формирует огромное количество мелких одиночных запросов к базе данных, что создаёт колоссальные накладные расходы на сетевой обмен и обработку каждого запроса на стороне СУБД.
Разберём подробнее причины такого поведения и проанализируем практические шаги, которые позволят вернуть высокую скорость работы системы.
При использовании штатных запросов или переборе объектов в циклах 1С 7.7 обращается к MS SQL Server не одним глобальным запросом, а множеством последовательных вызовов. Например, при формировании отчёта по остаткам система сначала выбирает идентификаторы номенклатуры из регистра, а затем для каждого элемента отдельным запросом запрашивает его наименование и реквизиты из таблицы справочника.
В DBF-версии это происходит мгновенно из локального кэша ОЗУ. В SQL Server каждый такой запрос требует проверки прав, анализа статистики, построения плана выполнения и сетевого круглого хода (round-trip), что при циклах на десятки тысяч строк приводит к замедлению в 5–10 раз.
По умолчанию MS SQL Server настроен на универсальную нагрузку и не учитывает специфику работы 1С 7.7. Для корректной работы СУБД с семеркой выполним следующие настройки:
MAXDOP = 1 в настройках сервера. В противном случае СУБД тратит больше времени на распараллеливание мелких запросов и ожидание потоков, чем на само выполнение.Lock Pages in Memory в локальных политиках безопасности Windows, чтобы предотвратить сброс рабочего множества памяти СУБД на диск.tempdb на отдельный быстрый SSD-диск и разобьем tempdb на несколько файлов одинакового размера (по числу ядер процессора).Shared Memory в сетевой конфигурации SQL Server, отключив остальные протоколы для локальных подключений.Проанализируем типовую ошибку в коде 1С 7.7, которая на DBF работает терпимо, а на SQL вызываeт катастрофическое падение производительности:
Пока Запрос.Группировка("Номенклатура") = 1 Цикл
// Каждое обращение через точку порождает отдельный SQL-запрос
Ставка = Запрос.Номенклатура.СтавкаНДС.Получить(Запрос.МоментВремени);
ПечататьСтроку(Запрос.Номенклатура.Наименование, Ставка);
КонецЦикла;
Чтобы устранить эту проблему, перепишем алгоритм с использованием кэширования в память:
ТЗ) перед началом цикла один раз.ТЗ по значению ключа с помощью НайтиЗначение() или предварительной индексации.Запрос.Док.Номенклатура.СтавкаНДС сначала присвоим объект локальной переменной: Ном = Запрос.Номенклатура;.Выясним еще одну частую причину медленного расчета остатков — наличие «зависших» итогов в таблицах регистров. Если при проведении документов расхода измерения заполняются не так, как при приходе (например, Приход был с указанием измерения Фирма, а Расход — с пустым значением), физический остаток по товару равен нулю, но в таблице итогов RG создаются две записи:
Эти нулевые суммарные остатки начинают переноситься из месяца в месяц как снежный ком. При расчете итогов SQL Server вынужден прочитывать миллионы ненужных записей. Для исправления ситуации проверим таблицы с помощью специализированных обработок или отчетов, выявляющих движения с несовпадающим набором измерений, и скорректируем модули проведения документов.
Самый эффективный способ ускорить отчёты и обработку данных в 1С 7.7 на MS SQL Server в десятки и сотни раз — использование прямой работы с СУБД через внешнюю компоненту 1С++ и объект ODBCRecordset.
Прямой запрос выполняются непосредственно на стороне SQL Server в один пасс, задействуя всю мощь T-SQL, соединения таблиц (JOIN) и агрегатные функции, возвращая на клиент уже готовый результат.
Рассмотрим пример выполнения прямого запроса для получения остатков номенклатуры:
ЗапросSQL = СоздатьОбъект("ODBCRecordset");
ТекстЗапроса = "
|SELECT
| RGT.sp123 AS [Номенклатура $Справочник.Номенклатура],
| SUM(RGT.sp124) AS [Остаток]
|FROM
| rg122 RGT (NOLOCK)
|WHERE
| RGT.period = :Период~
|GROUP BY
| RGT.sp123
|HAVING
| SUM(RGT.sp124) <> 0
|";
ЗапросSQL.УстановитьТекстовыйПараметр("Период", НачМесяца);
ТЗРезультат = ЗапросSQL.ВыполнитьИнструкцию(ТекстЗапроса);
Использование 1С++ и TurboBL позволяет избавиться от узких мест платформы 7.7 и достичь скорости работы отчетов, превышающей показатели даже файловой версии DBF.