1С тормозит: что делать - чек-лист диагностики
Иван Недомолков · Опубликовано: · Обновлено:
“1С тормозит, что делать?” - обычно этот вопрос задают, когда терпение уже кончилось: документ проводится две минуты, отчёт падает по таймауту, кассир ждёт список чеков 25 секунд. Первый рефлекс - купить сервер помощнее. Ниже - почему это чаще всего ошибка и какой чек-лист диагностики пройти вместо этого. Инструкция рассчитана на ИТ-специалиста или администратора; примеры и цифры - из наших боевых проектов.
Почему “купить сервер” - обычно ошибка
В восьми случаях из десяти причина медленной работы 1С не в железе. Причина - в запросе, который читает миллионы лишних строк; в отсутствующем индексе; в устаревшей статистике СУБД; в настройках SQL-сервера, оставленных “по умолчанию”; в блокировках между пользователями.
Новое железо в этих случаях даёт эффект от нуля до десятков процентов - при затратах в миллионы тенге. Устранение реальной причины даёт разы и порядки. Два примера из одного нашего проекта:
- Список чеков открывался ~25 секунд. После добавления индексов под кассовые операции - мгновенно. Логических чтений на операцию: 505 410 → 4. Никакой сервер не компенсирует запрос, который читает в 126 тысяч раз больше данных, чем нужно.
- “Вечерние зависания касс”, на которые все грешили на блокировки. Замер показал: блокировок ноль. Виноват был агрессивный параллелизм SQL на 48-ядерном сервере - заводские настройки cost threshold = 5 и MAXDOP = 0. Две настройки (5 → 50 и 0 → 8) - и вечерний пик перестал быть лотереей.
Во втором случае покупка сервера ещё мощнее сделала бы хуже: больше ядер - больше параллельных потоков на каждый мелкий запрос - больше конкуренции за них.
Есть и честная оговорка: иногда дело действительно в железе - диски не тянут, памяти мало, сервер делит ресурсы с соседями. Но выяснить это можно только замером, а не ощущениями. И замер тоже надо уметь прочитать: суточный максимум по диску показывал 97-99 % при среднем 4,24 %, то есть ресурс был свободен, а вывод напрашивался противоположный - разбор этой ошибки и что делать с памятью рабочего процесса. Отсюда чек-лист.
Чек-лист диагностики: 7 шагов
Порядок важен. Каждый шаг сужает круг подозреваемых, и большинство проблем находится до середины списка.
Шаг 1. Замер: зафиксируйте, что именно тормозит
Не “всё тормозит”, а конкретный список: какая операция, у кого, сколько секунд, когда началось. Без этого нельзя ни искать причину, ни проверить результат.
- Составьте список из 5-10 самых болезненных операций: “проведение реализации - 40 сек”, “ОСВ за квартал - 12 мин”, “открытие списка заказов - 20 сек”.
- Замерьте каждую 3-5 раз в разное время дня. Разброс сам по себе информативен: стабильные 40 секунд и “то 2, то 90” - разные диагнозы.
- Если в конфигурации есть подсистема оценки производительности (АПДЕКС из БСП) - включите её по ключевым операциям. Это скорость глазами пользователя, а не средняя температура по серверу.
- Отдельно зафиксируйте: тормозит у всех или у части пользователей, всегда или в пиковые часы, началось после конкретного события (обновление, переезд, рост базы) или деградировало плавно. Если при этом на сервере приложений загружен процессор, сначала найдите час, когда это началось: как искать, что грузит сервер 1С.
Если 1С медленно работает после обновления - это отдельная подсказка: после обновления конфигурации или платформы часто меняются тексты запросов и структура таблиц, а статистика СУБД остаётся старой. Обновление статистики и перестроение индексов по изменённым таблицам стоит сделать до любой другой диагностики.
Шаг 2. Технологический журнал 1С
Техжурнал - главный инструмент. Он показывает, какие запросы и чей код съедают время, с точностью до строки модуля.
- Настройте сбор событий DBMSSQL / DBPOSTGRS (длительные запросы) и TLOCK / TTIMEOUT / TDEADLOCK (ожидания и конфликты блокировок) с фильтром по длительности - например, от 5 секунд, чтобы не утонуть в логе.
- Соберите журнал за характерный период: рабочий день, включая пиковые часы.
- Сгруппируйте события по контексту (строке кода). Почти всегда картина концентрированная: 3-5 запросов дают 80 % всех длительных событий.
Типичная находка на этом шаге - запрос в цикле. В одном из наших проектов документ “не проводился” 2 минуты: остатки запрашивались отдельным запросом по каждой строке табличной части. После переписывания на один set-based запрос - 17 секунд. Код не менялся годами; просто данных стало больше.
Шаг 3. Планы запросов SQL
Техжурнал назвал запрос-виновник - теперь нужно понять, почему он медленный. Ответ - в плане запроса: как СУБД на самом деле его выполняет.
На что смотреть в первую очередь:
- Scan вместо Seek - сканирование всей таблицы там, где ожидался поиск по индексу. Причины: индекса нет, отбор по неиндексированному полю, функция поверх поля в условии.
- Расхождение оценки и факта - оптимизатор ожидал 100 строк, получил 10 миллионов. Это почти всегда устаревшая статистика; план строится под неверные предположения.
- Соединения с виртуальными таблицами без отборов - параметры виртуальной таблицы пустые, отбор навешан снаружи; СУБД сначала разворачивает всё, потом фильтрует.
- Логические чтения - самая честная метрика стоимости. 505 410 чтений на открытие списка - это диагноз независимо от того, сколько миллисекунд повезло получить из кэша.
Шаг 4. Статистика ожиданий СУБД
Планы объясняют отдельные запросы; статистика ожиданий - во что упирается сервер в целом. По ней видно, чем сервер занят, пока пользователь ждёт: диски, процессор, блокировки, память, параллелизм.
Грубая карта соответствий для MS SQL:
| Доминирующие ожидания | Куда копать |
|---|---|
| PAGEIOLATCH_* | Дисковая подсистема или запросы, читающие слишком много данных |
| LCK_M_* | Блокировки - см. шаг 5 |
| CXPACKET / CXCONSUMER | Параллелизм - см. шаг 6 |
| SOS_SCHEDULER_YIELD | Нехватка CPU или запросы, “жующие” процессор |
| RESOURCE_SEMAPHORE | Нехватка памяти на выполнение тяжёлых запросов |
| WRITELOG | Медленный диск под журналом транзакций |
Важно: ожидания смотрят за интервал, а не накопленным итогом с перезапуска сервера - иначе картина размазана событиями месячной давности.
Шаг 5. Блокировки
“Конфликт блокировок” и “превышено время ожидания” - симптомы, которые пользователи запоминают лучше всего. Но проверять надо фактами: события TTIMEOUT и TDEADLOCK в техжурнале, ожидания LCK_M_* в СУБД.
Если блокировки подтвердились, типовые причины такие:
- избыточные управляемые блокировки в самописном коде - блокируется больше, чем нужно;
- получение остатков внутри транзакции проведения - классика: чем дольше транзакция держит блокировку, тем длиннее очередь за ней;
- длинные транзакции - документ, который проводится 40 секунд, все эти 40 секунд держит заблокированными свои регистры;
- отсутствующие индексы: СУБД эскалирует блокировку с диапазона строк на таблицу.
Обратите внимание на порядок: медленный код порождает блокировки, а не наоборот. Ускорите проведение с 40 секунд до 2 - и “конфликты блокировок” часто исчезают сами, без единой правки логики блокировок.
И контрпример, о котором стоит помнить: в нашем проекте с “вечерними зависаниями касс” все были уверены, что это блокировки. Замер показал ноль конфликтов - причина была в параллелизме. Не лечите диагноз, поставленный по слухам.
Взаимоблокировки 1С: как отличить от ожидания
Взаимоблокировки 1С и конфликт управляемых блокировок пользователь видит одинаково: документ не провёлся. Механизмы разные. Конфликт управляемых блокировок - это ожидание: транзакция ждала чужую блокировку, по умолчанию около 20 секунд, и вышла по таймауту с текстом “Конфликт блокировок при выполнении транзакции”. Взаимоблокировка (deadlock) - это тупик на уровне СУБД: две транзакции держат то, что нужно друг другу, и SQL Server сразу откатывает одну из них с ошибкой 1205. Отсюда быстрый признак: висело секунд двадцать - это ожидание, упало сразу - дедлок. Дедлоки ищут не в техжурнале, а в сеансе system_health SQL Server, и разбирать надо частоты по десяткам отчётов, а не один случай из жалобы. Как это делается целиком, с запросами и замером, разобрано в статье “Взаимоблокировки 1С: как найти причину”.
Шаг 6. Параллелизм
Если тормозит 1С на сервере SQL, проверьте две настройки, которые почти всегда оставлены заводскими:
- Cost threshold for parallelism = 5 - порог 2005 года. На современном железе под него попадает почти любой запрос 1С, и СУБД распараллеливает даже мелочь.
- MAXDOP = 0 - без ограничения. Каждый такой “мелкий” запрос получает все ядра сервера.
Итог на многоядерном сервере: сотни коротких запросов OLTP-нагрузки 1С дерутся за ядра, накладные расходы на координацию потоков съедают эффект, в статистике ожиданий растут CXPACKET. На 48 ядрах мы наблюдали это в виде “лотереи” вечернего пика: cost threshold 5 → 50 и MAXDOP 0 → 8 сняли проблему без единой правки кода.
Универсальных значений нет - подбирать надо под профиль нагрузки и проверять замером. Но заводские 5 и 0 для 1С не подходят практически никогда.
Шаг 7. RLS и механизмы разграничения доступа
Если тормозит у одних пользователей и летает у других - с высокой вероятностью дело в RLS (ограничении доступа на уровне записей). Условия RLS дописываются к каждому запросу пользователя, и “лишние” соединения в них умножают стоимость любого списка и отчёта.
Масштаб бывает неожиданным: в одном из наших проектов список чеков под кассиром (с учётом RLS) выполнял 162 млн логических чтений. После перехода с универсального механизма ограничения доступа на классический (отбор по подразделению прямо в запросах списков) - 94 чтения.
Диагностика простая: сравните время операции под полными правами и под ограниченными. Разница в разы - это RLS.
Типовые причины: сводная таблица
| Причина | Типичный симптом | Как подтвердить | Что даёт устранение |
|---|---|---|---|
| Запрос в цикле | Долгое проведение документов, время растёт с числом строк | Техжурнал: один контекст, тысячи однотипных запросов | Разы (у нас: 2 мин → 17 сек) |
| Отсутствующий индекс | Медленный список или отчёт с отбором | План запроса: Scan вместо Seek | Разы и порядки (505 410 → 4 чтения) |
| Устаревшая статистика | Резкая деградация после обновления или массовой загрузки | План: оценка строк расходится с фактом | Возврат к норме |
| Заводской параллелизм | Хаотичные тормоза в пик на многоядерном сервере | Ожидания CXPACKET; cost threshold = 5, MAXDOP = 0 | Стабильный пик |
| Блокировки | ”Конфликт блокировок” при многих пользователях | TTIMEOUT/TDEADLOCK в техжурнале, LCK_M_* в СУБД | Исчезновение ошибок ожидания |
| Тяжёлый RLS | Тормозит под ограниченными правами, летает под полными | Сравнение замеров под разными правами | Разы (162 млн → 94 чтения) |
| Виртуальные таблицы без отборов | Медленные отчёты на СКД и в коде | План: фильтрация после разворачивания таблицы | Десятки процентов - разы |
| Сосед по серверу | Тормозит “иногда”, без корреляции со своей нагрузкой | Мониторинг инстанса: чужая база в топе по ресурсам | Стабильность |
Последний пункт недооценивают. В одном из наших проектов на общем инстансе чужой отчёт из соседней базы работал 4,3 часа в 24 параллельных потока - и душил кассы, к которым не имел никакого отношения. Изнутри “своей” базы такое не видно в принципе; нужен взгляд на весь сервер.
Как ускорить 1С: что обычно даёт результат
По итогам диагностики список правок почти всегда компактный - потому что и виновников немного. Типовой набор в наших проектах:
- Переписать 3-5 запросов-лидеров техжурнала: убрать циклы, добавить отборы в виртуальные таблицы, вынести лишнее из транзакций.
- Добавить индексы под реальные сценарии отборов - не “на всякий случай”, а по планам запросов.
- Привести в порядок статистику и обслуживание индексов на уровне СУБД.
- Настроить параллелизм, память, tempdb под профиль 1С.
- Если подтвердился тяжёлый RLS - упростить схему ограничений.
И отдельный пункт, который отличает диагностику от “оптимизации вслепую”: часть операций после разбора мы оставляем без изменений. В одном проекте несколько отчётов из списка жалоб были именно такими - узкое место оказалось не в запросе, и переписывание не дало бы измеримого выигрыша. Не потратить бюджет на то, что не ускорится, - тоже результат диагностики.
Каждую правку проверяйте замером против цифр из шага 1. Для отчётов полезна жёсткая проверка эквивалентности: мы сверяем результат “до” и “после” контрольной суммой SHA-256, чтобы ускорение не оказалось следствием потерянных данных. Так шесть тяжёлых управленческих отчётов в нашем проекте ускорились на 22-42 % - при побайтово идентичном результате.
И сам замер стоит устроить так, чтобы ему можно было верить. На боевой базе, где кроме вас работают люди, три прогона с выбором минимума дают ускорение, которого нет: минимум ловит самый удачный момент. Проверяется чередованием до и после в одном окне - как это считать и что делать с тяжёлым отчётом, который нельзя прогнать восемь раз.
Когда пора звать специалистов
Чек-лист выше реально пройти своими силами, если в команде есть человек, знакомый с техжурналом и планами запросов. Звать внешних специалистов имеет смысл, когда:
- техжурнал и планы запросов в команде никто не читает - а учиться на боевой базе дорого;
- диагностика прошла, виновник найден, но это код типовой конфигурации или сложный механизм (RLS, итоги регистров), который страшно трогать;
- проблема плавающая: “то работает, то нет”, и поймать её разовым замером не получается - нужен постоянный сбор техжурнала и мониторинг;
- база выросла до сотен гигабайт или терабайт, и тормоза - лишь один из симптомов (вместе с бэкапами на всю ночь и заканчивающимся местом). Тогда вопрос шире, чем оптимизация: см. наш разбор “обрезки базы 4,2 ТБ → 105 ГБ”, где ускорение касс и сокращение базы в 40 раз были частями одной работы;
- сервер общий, и надо разбираться с влиянием соседних баз.
Живой пример того, как рефлекс “вечером тормозит - значит блокировки” уводит в сторону, разобран в нашей статье на Инфостарте: “Все думали на блокировки: детектив о вечернем пике” - там блокировок оказалось ноль, а кассы душил параллелизм на заводских настройках сервера.
Что даёт такой подход на живом высоконагруженном процессе - в кейсе “Ценообразование для маркетплейсов: в 2-6 раз быстрее”: там один запрос ускорился с 39 минут до 6 секунд, а итоговые цены остались бит-в-бит теми же.
Мы проводим такую диагностику как отдельную услугу - оптимизация производительности 1С: замер, техжурнал, планы запросов, правки с подтверждением “до/после” по каждой операции. Начать можно с бесплатного экспресс-аудита - за короткую сессию обычно уже видно, в какой из семи шагов чек-листа упирается ваша база, и что даст эффект: правка запросов, настройка СУБД или, в редком честном случае, действительно железо.
Готовая обработка по теме
Если тормозит именно СУБД, а не конкретный запрос: Чек-ап СУБД под 1С за один прогон проверяет 40+ настроек SQL Server и показывает, что стоит неправильно.
Сколько стоит привести базу в порядок - на странице цен: оптимизация от 150 000 ₸, свертка от 450 000 ₸, всё без налогов и с фиксацией после бесплатного аудита. Цена от города не зависит, но если удобнее начать с местного контекста - есть страницы про услуги 1С в Алматы, Астане и Шымкенте.
Частые вопросы
Что такое взаимоблокировки в 1С и чем они опасны?
Взаимоблокировка - это тупик двух транзакций в СУБД: каждая ждёт ресурс, который держит другая. SQL Server решает его сам, откатывая одну транзакцию с ошибкой 1205, поэтому база не зависает, но у пользователя не проводится документ. Опасны они частотой: редкий дедлок почти незаметен, а когда их десятки в час, это уже поиск причины. В нашем разборе виновником оказался отсутствующий индекс на реквизите составного типа, а таблицы из жалобы пользователя среди виновников не было вовсе.
Как понять, что тормоза от блокировок, а не от сервера?
По фактам из шага 5: события TLOCK, TTIMEOUT и TDEADLOCK в технологическом журнале и ожидания LCK_M_* в статистике ожиданий СУБД. Если их нет, а тормоза есть, причина в другом слое, и лечить блокировки бессмысленно.
Если релиз не менялся, сравните объём работы
Тот же код может получать больше строк, чаще вызываться или обрабатывать другой состав данных. Проверьте количество элементов входной коллекции и число обращений к данным на одну операцию. Рост времени быстрее роста объёма указывает на участок для исследования, но сам по себе ещё не доказывает конкретную сложность алгоритма: на результат влияют ожидания, кэш и параллельная нагрузка.
На копии выполните один сценарий с разными контролируемыми объёмами входных данных. Не удаляйте половину документов ради опыта: выберите отбор или пакет, который не меняет смысл операции. Сохраните объём, длительность и условия каждого прогона. Затем проверьте в профиле, увеличилось ли число вызовов или подорожал один вызов.
Если причина проявляется только под нагрузкой, нужен короткий сбор технологического журнала. Настроить сбор и разобрать события, в том числе выгрузить их для нейросети, помогает обработка разбора технологического журнала. Когда подозрение падает на обслуживание сервера, начните с сопоставления настроек кластера и состояния процессов, чтобы не править запрос из-за ожидания, возникшего в другом слое.