Почему CRM в Битрикс24 тормозит на 50К сделок и что с этим делать

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Когда в CRM пара тысяч сделок, всё летает. На десяти тысячах появляются первые паузы. На пятидесяти тысячах список сделок открывается по 8–15 секунд, фильтрация по пользовательским полям зависает, менеджеры жалуются, что «Битрикс тормозит». Обычно кто‑то предлагает «перейти на другую CRM» или «купить сервер помощнее», но оба варианта мимо: проблема не в Битриксе и не в железе, а в том, как данные хранятся и запрашиваются.

Рассмотрим конкретные причины и посмотрим, что с каждой делать.

Начинаем с диагностики, а не с оптимизации

Прежде чем что‑то чинить, нужно понять, что именно тормозит. Включите slow query log в MySQL:

# my.cnf
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
log_queries_not_using_indexes = 1

Последняя строка очень важна: она логирует запросы, которые не используют индексы, даже если они укладываются в секунду. На малых объёмах они проходят незаметно, на больших встают в пробку.

Перезапустите MySQL, воспроизведите проблему (откройте тот самый тормозящий список сделок) и посмотрите в лог. Обычно первые три‑четыре запроса в логе — это 80% проблемы.

Для каждого подозрительного запроса делайте EXPLAIN:

EXPLAIN SELECT d.ID, d.TITLE, d.STAGE_ID 
FROM b_crm_deal d
JOIN b_uts_crm_deal uf ON uf.VALUE_ID = d.ID
WHERE uf.UF_CRM_1234567890_REGION = 'Moscow'
ORDER BY d.DATE_CREATE DESC
LIMIT 50;

Если в колонке type видите ALL — это full table scan, запрос читает всю таблицу. Если rows показывает число, сопоставимое с количеством записей в таблице то же самое. Ищите такие запросы и работайте с ними.

Для D7 ORM можно вытащить сгенерированный SQL прямо из кода. Это помогает, когда вы не знаете, какой запрос генерирует конкретный getList:

\Bitrix\Main\Application::getConnection()->startTracker();

$deals = \Bitrix\Crm\DealTable::getList([
    'filter' => ['=STAGE_ID' => 'NEW'],
    'select' => ['ID', 'TITLE'],
    'limit' => 50,
]);

$tracker = \Bitrix\Main\Application::getConnection()->getTracker();
foreach ($tracker->getQueries() as $query) {
    error_log($query->getSql());
    error_log("Time: " . $query->getTime());
}

Теперь вы видите конкретный SQL с конкретным временем выполнения.

Источник: https://habr.com/ru/companies/otus/articles/1029706/


Интересные статьи

Интересные статьи

DISCLAIMER: Данная статья не является «статьёй конкурента» (поскольку у моей нынешней IT-компании нет продуктов, конкурирующих с изделиями Bitrix) или какой-то «заказной» (поскольку вряд ли кто-то мне...
Всем привет! Мы перевели работу hr-менеджеров в Битрикс24. Расскажем как выглядит воронка и какие есть преимущества.В первую очередь пишем данную статью для тех, кто в компании уже использует Битрикс2...
Всем привет, на связи юрист ispmanager Олег Макаров. Расскажу, как попасть в обязательный с 1 февраля 2024 года реестр хостеров, какие правила придется соблюдать и как накажут, если этого не сдел...
Привет, Хабр! Мы в Smart Engines постоянно пополняем список документов, которые под силу распознать нашим системам Smart ID Engine и Smart Document Engine. На сегодняшний день их количество исчисляетс...
Реализация ORM в ядре D7 — очередная интересная, перспективная, но как обычно плохо документированная разработка от 1с-Битрикс :) Призвана она абстрагировать разработчика от механики работы с табл...