Проблема клиента Битрикс - долго выполняется запрос. innotop показывает печальную картину:
CXN When Load QPS Slow QCacheHit KCacheHit BpsIn BpsOut
local Now 0.00 286.87 0 68.14% 99.20% 279.27k 1.14M
local Total 0.00 259.85 3 71.51% 99.08% 219.76k 1.44M
CXN Cmd ID User Host DB Time Query
local Query 132330 bitrix 192.168.0.1 bitrix 01:01:07 SELECT DISTINCT
local Query 158219 bitrix 192.168.0.1 bitrix 12:37 SELECT DISTINCT
Попытаемся разобраться. Версия MySQL не самая старая
mysql> select version();
+--------------------------+
| version() |
+--------------------------+
| 5.0.32-Debian_7etch6-log |
+--------------------------+
1 row in set (0.00 sec)
Выясним, что это за долгоиграющий запрос и в каком статусе находится?
mysql> show full processlist;
...
| 132330 | bitrix | 192.168.0.1:45057 | bitrix | Query | 3612 | statistics |
SELECT DISTINCT BE.ID as ID,BE.NAME as NAME,BE.XML_ID as EXTERNAL_ID,BE.IBLOCK_ID as IBLOCK_ID,BE.IBLOCK_SECTION_ID as IBLOCK_SECTION_ID,B.DETAIL_PAGE_URL as DETAIL_PAGE_URL,BE.PREVIEW_PICTURE as PREVIEW_PICTURE, FPV1.VALUE as PROPERTY_MANUFACTURER_SRC_VALUE, FPV1.ID as PROPERTY_MANUFACTURER_SRC_VALUE_ID, FPEN2.VALUE as PROPERTY_STICKERS_VALUE, FPEN2.ID as PROPERTY_STICKERS_ENUM_ID, FPV2.ID as PROPERTY_STICKERS_VALUE_ID, FPV4.VALUE as PROPERTY_ARTICULS_VALUE, FPV4.ID as PROPERTY_ARTICULS_VALUE_ID, FPV5.VALUE as PROPERTY_RATE_VALUE, FPV5.ID as PROPERTY_RATE_VALUE_ID,L.DIR as LANG_DIR,BE.CODE as CODE,B.IBLOCK_TYPE_ID as IBLOCK_TYPE_ID,B.CODE as IBLOCK_CODE,B.XML_ID as IBLOCK_EXTERNAL_ID FROM b_iblock B INNER JOIN b_lang L ON B.LID=L.LID INNER JOIN b_iblock_element BE ON BE.IBLOCK_ID = B.ID INNER JOIN b_iblock_section_element BSE ON BSE.IBLOCK_ELEMENT_ID = BE.ID INNER JOIN b_iblock_section BS ON BSE.IBLOCK_SECTION_ID = BS.ID LEFT JOIN b_iblock_property FP1 ON FP1.IBLOCK_ID=B.ID AND FP1.CODE='MANUFACTURER_SRC' LEFT JOIN b_iblock_element_property FPV1 ON FP1.ID=FPV1.IBLOCK_PROPERTY_ID AND FPV1.IBLOCK_ELEMENT_ID=BE.ID LEFT JOIN b_iblock_property FP2 ON FP2.IBLOCK_ID=B.ID AND FP2.CODE='STICKERS' LEFT JOIN b_iblock_element_property FPV2 ON FP2.ID=FPV2.IBLOCK_PROPERTY_ID AND FPV2.IBLOCK_ELEMENT_ID=BE.ID LEFT JOIN b_iblock_property_enum FPEN2 ON FP2.ID = FPEN2.PROPERTY_ID AND FPV2.VALUE_ENUM=FPEN2.ID LEFT JOIN b_iblock_property FP4 ON FP4.IBLOCK_ID=B.ID AND FP4.CODE='ARTICULS' LEFT JOIN b_iblock_element_property FPV4 ON FP4.ID=FPV4.IBLOCK_PROPERTY_ID AND FPV4.IBLOCK_ELEMENT_ID=BE.ID LEFT JOIN b_iblock_property FP5 ON FP5.IBLOCK_ID=B.ID AND FP5.CODE='RATE' LEFT JOIN b_iblock_element_property FPV5 ON FP5.ID=FPV5.IBLOCK_PROPERTY_ID AND FPV5.IBLOCK_ELEMENT_ID=BE.ID INNER JOIN b_iblock_property FP6 ON FP6.IBLOCK_ID=B.ID AND FP6.CODE='MANUFACTURER' INNER JOIN b_iblock_element_property FPV6 ON FP6.ID=FPV6.IBLOCK_PROPERTY_ID AND FPV6.IBLOCK_ELEMENT_ID=BE.ID INNER JOIN b_iblock_property FP7 ON FP7.IBLOCK_ID=B.ID AND FP7.CODE='BIG_PHOTO' INNER JOIN b_iblock_element_property FPV7 ON FP7.ID=FPV7.IBLOCK_PROPERTY_ID AND FPV7.IBLOCK_ELEMENT_ID=BE.ID INNER JOIN b_iblock_property_enum FPEN7 ON FP7.ID = FPEN7.PROPERTY_ID AND FPV7.VALUE_ENUM=FPEN7.ID INNER JOIN b_iblock_property FP9 ON FP9.IBLOCK_ID=B.ID AND FP9.CODE='BIG_PLANS' INNER JOIN b_iblock_element_property FPV9 ON FP9.ID=FPV9.IBLOCK_PROPERTY_ID AND FPV9.IBLOCK_ELEMENT_ID=BE.ID INNER JOIN b_iblock_property_enum FPEN9 ON FP9.ID = FPEN9.PROPERTY_ID AND FPV9.VALUE_ENUM=FPEN9.ID INNER JOIN b_iblock_property FP11 ON FP11.IBLOCK_ID=B.ID AND FP11.CODE='STABILIZATION' INNER JOIN b_iblock_element_property FPV11 ON FP11.ID=FPV11.IBLOCK_PROPERTY_ID AND FPV11.IBLOCK_ELEMENT_ID=BE.ID INNER JOIN b_iblock_property FP12 ON FP12.IBLOCK_ID=B.ID AND FP12.CODE='PHOTO_RESOLUTION' INNER JOIN b_iblock_element_property FPV12 ON FP12.ID=FPV12.IBLOCK_PROPERTY_ID AND FPV12.IBLOCK_ELEMENT_ID=BE.ID INNER JOIN b_iblock_property FP13 ON FP13.IBLOCK_ID=B.ID AND FP13.CODE='OPTICAL_ZOOM' INNER JOIN b_iblock_element_property FPV13 ON FP13.ID=FPV13.IBLOCK_PROPERTY_ID AND FPV13.IBLOCK_ELEMENT_ID=BE.ID WHERE 1=1 AND B.ID IN (0,21) AND ( (BE.WF_STATUS_ID=1 AND BE.WF_PARENT_ELEMENT_ID IS NULL) ) AND (((BE.ACTIVE_TO >= now() OR BE.ACTIVE_TO IS NULL) AND (BE.ACTIVE_FROM <= now() OR BE.ACTIVE_FROM IS NULL))) AND ((((BE.ACTIVE='Y')))) AND ((((FPV6.VALUE_NUM = '218232')) OR ((FPV6.VALUE_NUM = '218235')) OR ((FPV6.VALUE_NUM = '218237')) OR ((FPV6.VALUE_NUM = '218238')))) AND ((((FPEN7.VALUE LIKE 'ДА')))) AND ((((FPEN9.VALUE LIKE 'ДА')))) AND ((((FPV11.VALUE_ENUM = '1388')))) AND ((((FPV12.VALUE >= '8')))) AND ((((FPV13.VALUE >= '5')))) AND ((BS.ID = 1481))
Интересно, что команда EXPLAIN для этого запроса выполняется так же долго и "висит" в том же состоянии. Запрос сам по себе, конечно, жутковатый - объединение более 30 таблиц, но это не повод выполняться долго.
К счастью там же упоминаются параметры, которые напрямую влияют на длительность фазы оптимизации запроса сервера MySQL. Один из них представляется важным в нашей ситуации optimizer_search_depth:
mysql> show global variables like 'optimizer_search_depth';
+------------------------+-------+
| Variable_name | Value |
+------------------------+-------+
| optimizer_search_depth | 62 |
+------------------------+-------+
Установлено значение по умолчанию, попробуем уменьшить, как рекомендуется в документации MySQL и проверить на примере команды EXPLAIN:
mysql> explain select...
Query aborted by Ctrl+C
Empty set (4.90 sec)
прервал, всё по-прежнему долго
mysql> set session optimizer_search_depth=30;
Query aborted by Ctrl+C
Empty set (7.92 sec)
прервал, долго
mysql> set session optimizer_search_depth=10;
28 rows in set (0.22 sec)
намного лучше! Попробуем предоставить оптимизатору MySQL самому подобрать значение параметра:
mysql> set session optimizer_search_depth=0;
28 rows in set (0.03 sec)
Значит может, если захочет! Странно то, что этот параметр по умолчанию установлен в значение 62 - можно даже предположить, что разработчики MySQL надеются успешно бороться с запросами о 60-ти таблицах %)
В случае положительного результата можно попробовать выполнить с новым значением параметра типичные небыстрые запросы Битрикса, которые можно получить из "Монитора производительности", чтобы убедиться, что изменение этого параметра не скажется отрицательно на производительности всей системы. И только после этого в период минимальной нагрузки (например, в 04:00 можно попробовать изменить параметр для всей системы:
2) Описанная проблема не является багом Битрикса и сложные запросы тут ни при чём. Клиент сам выбирает базу данных, а MySQL - активно развивающийся продукт.
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».