Если у вас возникли какие либо вопросы которые вы не смогли решить по нашим публикациям самостоятельно,
то ждем ваше обращение в нашей службе тех поддержки.
Кардинально ускоряем Bitrix+MSSQL
В этом посте я хотел бы рассказать о своём опыте оптимизации работы Битрикса, работающего на Windows-платформе под MSSQL.
Начать разбираться с производительностью такой связки меня побудило исключительно появление версии 8.5 с переработанным модулем "Производительность". Именно возможность получить оценку своего хостинга и сравнить с другими площадками дала толчок этому исследованию. Итак, как только вышла версия 8.5, то я первым делом полез в панель производительности, чтобы увидеть заветные цифры. Радость обновления Битрикса сменилась горечью результата: где-то в районе 4-6 на не самом плохом оборудовании.
Оптимизация №1
При анализе и игре с настройками php и Битрикса я заметил упоминание про WinCache, о котором раньше не слышал. Немного поиска выдало хорошие рекомендации "лучших собаководов" и красивые графики роста производительности. Настройка и установка прошли легко и их итог хорошо виден тут:
Радоваться можно было уже от этого результата, все показатели разом улучшились где-то в 2 раза, сайт и админка стали заметно быстрее загружаться. Однако было грустно от полученных значений БД, особенно чтения. 1000-1200 -- это совсем не то, что может выдавать выделенный MSSQL сервер, поэтому...
Оптимизация №2
Первым делом был разобран сам модуль производительности и из него был извлечён модуль оценки БД. Для него я подстроил имевшийся в запасниках мини класс для работы с базой данных, но через драйвер sqlsrv. Запуск в консоли показал интересный результат в 3200+ запросов на чтение, что было в 3(!) раза больше, чем в тесте Битрикса(скриншот выше). Использование аналогичного мини класса, но на odbc, показало значение около 1200.
Неужели драйвер odbc так сильно проигрывает драйверу от Microsoft? Возможно, но корень зла оказался немного в другом.
Получив такой неожиданный результат появился профессиональный азарт "перебрать двигатель" Битрикса, а именно его класс работы с БД в
/bitrix/modules/main/classes/mssql/database.php
и перевести его на рельсы sqlsrv. Эта задача не такая и сложная, все вызовы очень похожи, лишь немного переделан код получения данных:
При хранении сессий в базе данных нужно аналогично отредактировать /bitrix/modules/security/classes/mssql/session.php (других мест прямых вызов odbc найдено не было)
в dbconn.php нужно будет исправить $DBHost, чтобы он указывал сразу на сервер
Единственный тонкий момент, который возник, это постраничный забор данных(в NavQuery), который был решён использованием SQLSRV_CURSOR_STATIC. Всё казалось готовым к старту, ключ зажигания включен и вроде бы взлетели: сайт вёл себя адекватно, проблем вроде не замечено. Вот только особого ускорения не почувствовалось, что подтвердили тесты: общая производительность поднялась где-то на 1-2 балла, и количество чтений БД выросло лишь "в пределах погрешности измерений".
"Так не бывает и должно быть разумное объяснение" крутилось в голове и оно было найдено... после отключения SQLSRV_CURSOR_STATIC:
Корень зла оказался в курсорах. По умолчанию в odbc выбран статический курсор (SQL_CURSOR_STATIC), который позволяет произвольно перемещаться вперёд-назад по выборке. Драйвер sqlsrv наоборот по умолчанию задаёт тип последовательный курсор(SQLSRV_CURSOR_FORWARD), способный двигаться только вперёд. Во всём коде database.php есть лишь одно место, где реально используются переходы курсоров, а именно в NavQuery. Там пролистываются результаты до нужной страницы, если не установлен NavShowAll. Более того, записи листаются исключительно вперёд.
Возникает вопрос к разработчикам Битрикса: а так ли необходимо использовать *_CURSOR_STATIC, серьёзно терять в производительности, и всё ради мнимого удобства переключения на N-ую запись? Может лучше быстро сделать sqlsrv_fetch или odbc_fetch_row нужное количество раз?
Из тех 20-50+ запросов, что делает Битрикс, не более десяти реально будут использовать навигацию, в то время как остальные тратят драгоценные ресурсы на создание статических курсоров.
Итог
Достигнутый результат полностью удовлетворяет. Производительность поднялась кардинально, что отражает скачок оценки от ~5 до ~21, страницы стали загружаться ощутимо быстрее, время отклика упало с ~900мс до ~300мс.
P.S. Попытка сделать последовательный курсор в ODBC успехом не увенчалась, возможно я что-то делал не так, но желания копаться уже нет.
P.P.S. Применение второго метода оптимизации конечно же предлагается в варианте "As Is" без каких либо гарантий.