Многие администраторы и программисты сталкиваются с парадоксальной ситуацией: старая база 1С версии 7.7 (формат DBF), перенесенная на новый, современный и мощный сервер, начинает работать медленнее, чем на старом «железе». Особенно сильно деградирует скорость выполнения запросов с условиями фильтрации. Рассмотрим эту проблему подробно, проанализируем причины и разберем эффективные методы оптимизации, собранные на основе опыта профессионального сообщества.
В исходном примере мы имеем файловую базу размером около 10 Гб. Простейший запрос с условием вхождения элемента в список выполняется 50 секунд. Почему так происходит?
Давайте разберемся, что означает «мощный сервер» для 1С 7.7. Платформа 7.7 — это 32-битное однопоточное приложение. Ему совершенно безразлично, что у вас 32 ядра процессора. Оно использует только одно ядро. Современные серверные процессоры часто имеют более низкую базовую частоту на одно ядро (например, 2.2 ГГц), чем старые десктопные процессоры (3.0 ГГц и выше). В итоге, для однопоточной задачи новый сервер может оказаться медленнее.
Кроме того, узким местом файловой версии является дисковая подсистема, а именно работа с множеством мелких временных файлов.
Одной из главных причин тормозов стандартных («черных») запросов в 1С 7.7 является специфическая работа с временными файлами.
При выполнении запроса платформа активно использует каталог временных файлов. Причем, как отмечают эксперты, кэширование записи и чтения для этих операций часто работает некорректно или отключается платформой принудительно. Это приводит к тому, что 1С буквально за каждой записью обращается к физическому диску, создавая огромную очередь ввода-вывода (IOPS).
Что мы можем сделать?
Самое действенное и простое решение — перенести временные файлы 1С в оперативную память. Для этого нам понадобится создать RAM-диск.
/T (латинская T) в командной строке или ярлыке запуска.Пример строки запуска:
"C:\Program Files\1Cv77\BIN\1cv7s.exe" enterprise /D"C:\Base1C\" /N"User" /P"Pass" /T"R:\Temp1C"
Где R:\Temp1C — это путь к папке на вашем быстром RAM-диске. Это решение исключает физические задержки жесткого диска (даже SSD) при формировании временных таблиц запроса.
Если база данных выросла до 10 Гб, стандартный механизм запросов 1С (Query) перестает справляться. Когда вы используете конструкцию вида:
|Условие(Номенклатура в ВыбНоменклатура);
Штатный движок часто сначала считывает огромный объем данных из DBF-файлов, сбрасывает их во временный файл, и только потом накладывает фильтр. Это крайне неэффективно.
Профессиональным стандартом де-факто для больших баз на 7.7 является использование внешних компонент для прямых запросов, например, 1SQLite или 1C++.
Преимущества прямых запросов:
Давайте посмотрим, как можно заменить штатный запрос на прямой с использованием 1SQLite:
// Подключение компоненты (примерный код)
ЗагрузитьВнешнююКомпоненту("1sqlite.dll");
БД = СоздатьОбъект("SQLiteBase");
БД.Открыть(":memory:");
Запрос = БД.НовыйЗапрос();
// Текст прямого запроса
ТекстЗапроса = "
|SELECT
| Spr.Code as Код,
| Spr.Descr as Наименование
|FROM
| [Справочник.Номенклатура] as Spr
|WHERE
| Spr.ID IN (SELECT Val FROM @Spisok)
|";
// Передача списка значений как параметра
Запрос.УложитьСписок(ВыбНоменклатура, "Spisok");
ТзРезультат = Запрос.ВыполнитьЗапрос(ТекстЗапроса);
Это требует переписывания кода, но дает самый значительный прирост производительности.
На новых серверах часто по умолчанию включен Защитник Windows или установлен корпоративный антивирус. Файловая база 1С 7.7 генерирует тысячи обращений к файлам в секунду. Если антивирус пытается проверить каждый файл .dbf, .cdx или временный .tmp при доступе к нему, "тормоза" неизбежны.
Обязательные действия:
dbf, cdx, md, dd, tmp.1cv7.exe или 1cv7s.exe.Также рекомендуется настроить схему электропитания сервера на режим «Высокая производительность», чтобы процессор не сбрасывал частоту ядер при прерывистой нагрузке, характерной для работы 1С.
Если использование внешних компонент невозможно, проанализируем код самого запроса. Конструкция условия с вхождением в список (Условие(Х в Списке)) работает медленно, если список большой или оптимизатор 1С ошибается с выбором индекса.
Иногда быстрее работает отказ от условия в запросе и фильтрация результатов уже в памяти:
// Вместо фильтра в запросе выгружаем всё (или фильтруем только по статичным признакам)
Запрос.Выполнить(ТекстЗапроса);
Пока Запрос.Группировка(1) = 1 Цикл
// Фильтруем "руками"
Если СписокНужнойНоменклатуры.Принадлежит(Запрос.Номенклатура) = 0 Тогда
Продолжить;
КонецЕсли;
// Обработка данных
КонецЦикла;
В некоторых случаях, особенно при сложной логике условий в 7.7, такой подход работает быстрее, так как перебор в памяти процессора происходит мгновенно по сравнению с дисковыми операциями движка запросов.
Не забывайте про базовое обслуживание. Если запросы стали тормозить внезапно, проверьте следующие моменты:
*.cfg в папках пользователей (предварительно сделав бэкап). Иногда там накапливается "мусор" с настройками окон и списков, который платформа долго читает.*.cdx (индексные файлы) при выключенной 1С и запустите программу монопольно. Это заставит 1С создать индексы заново, что устранит их фрагментацию и возможные ошибки.База 1С 7.7 на DBF размером 10 Гб находится в зоне технического риска, так как предельный размер одного файла DBF составляет 2 Гб. Наилучшим стратегическим решением будет переход на SQL-версию 1С 7.7 или миграция на платформу 1С 8. Однако, чтобы обеспечить быструю работу "здесь и сейчас", использование RAM-диска для временных файлов и переход на прямые запросы (1SQLite) являются самыми эффективными методами.