На сайте формирую фильтр для компонента catalog.section.
Если параметров фильтрации до 4х то компонент отрабатывает быстро (до секунды). Пример фильтра:
Array
(
[PROPERTY_PURPOSE] => 1075
[PROPERTY_SPHERE] => 1073
[PROPERTY_KIND] => 1084
[PROPERTY_MATERIAL] => 2808
)
Если использовать 5й параметр в фильтре то время выполнения резко увеличивается до минуты, если 6й - то загрузки уже не дождаться.
Анализ производительности показал что долго выполняются запросы к базе. Вот пример запроса, который выполняется минуту, тут фильтрация по 5ти параметрам:
SELECT DISTINCT BE.ID as ID
,BE.IBLOCK_ID as IBLOCK_ID
,BE.CODE as CODE
,BE.XML_ID as XML_ID
,BE.NAME as NAME
,BE.ACTIVE as ACTIVE
,IF(EXTRACT(HOUR_SECOND
FROM
BE.ACTIVE_FROM)>0, DATE_FORMAT(BE.ACTIVE_FROM, '%d.%m.%Y %H:%i:%s'), DATE_FORMAT(BE.ACTIVE_FROM, '%d.%m.%Y')) as DATE_ACTIVE_FROM
,IF(EXTRACT(HOUR_SECOND
FROM
BE.ACTIVE_TO)>0, DATE_FORMAT(BE.ACTIVE_TO, '%d.%m.%Y %H:%i:%s'), DATE_FORMAT(BE.ACTIVE_TO, '%d.%m.%Y')) as DATE_ACTIVE_TO
,BE.SORT as SORT
,BE.PREVIEW_TEXT as PREVIEW_TEXT
,BE.PREVIEW_TEXT_TYPE as PREVIEW_TEXT_TYPE
,BE.DETAIL_TEXT as DETAIL_TEXT
,BE.DETAIL_TEXT_TYPE as DETAIL_TEXT_TYPE
,DATE_FORMAT(BE.DATE_CREATE, '%d.%m.%Y %H:%i:%s') as DATE_CREATE
,BE.CREATED_BY as CREATED_BY
,DATE_FORMAT(BE.TIMESTAMP_X, '%d.%m.%Y %H:%i:%s') as TIMESTAMP_X
,BE.MODIFIED_BY as MODIFIED_BY
,BE.TAGS as TAGS
,BE.IBLOCK_SECTION_ID as IBLOCK_SECTION_ID
,B.DETAIL_PAGE_URL as DETAIL_PAGE_URL
,BE.DETAIL_PICTURE as DETAIL_PICTURE
,BE.PREVIEW_PICTURE as PREVIEW_PICTURE
, FPS0.*
,L.DIR as LANG_DIR
,BE.XML_ID as EXTERNAL_ID
,B.IBLOCK_TYPE_ID as IBLOCK_TYPE_ID
,B.CODE as IBLOCK_CODE
,B.XML_ID as IBLOCK_EXTERNAL_ID
,B.LID as LID
, CAT_P4.ID as CATALOG_PRICE_ID_4
, CAT_P4.CATALOG_GROUP_ID as CATALOG_GROUP_ID_4
, CAT_P4.PRICE as CATALOG_PRICE_4
, CAT_P4.CURRENCY as CATALOG_CURRENCY_4
, CAT_P4.QUANTITY_FROM as CATALOG_QUANTITY_FROM_4
, CAT_P4.QUANTITY_TO as CATALOG_QUANTITY_TO_4
, '' as CATALOG_GROUP_NAME_4
, 'Y' as CATALOG_CAN_ACCESS_4
, 'Y' as CATALOG_CAN_BUY_4
, CAT_P4.EXTRA_ID as CATALOG_EXTRA_ID_4
, CAT_PR.QUANTITY as CATALOG_QUANTITY
, IF (CAT_PR.QUANTITY_TRACE = 'D', 'N', CAT_PR.QUANTITY_TRACE) as CATALOG_QUANTITY_TRACE
, CAT_PR.QUANTITY_TRACE as CATALOG_QUANTITY_TRACE_ORIG
, IF (CAT_PR.CAN_BUY_ZERO = 'D', 'N', CAT_PR.CAN_BUY_ZERO) as CATALOG_CAN_BUY_ZERO
, IF (CAT_PR.NEGATIVE_AMOUNT_TRACE = 'D', 'N', CAT_PR.NEGATIVE_AMOUNT_TRACE) as CATALOG_NEGATIVE_AMOUNT_TRACE
, IF ( CAT_PR.QUANTITY > 0 OR IF (CAT_PR.QUANTITY_TRACE = 'D', 'N', CAT_PR.QUANTITY_TRACE) = 'N' OR IF (CAT_PR.CAN_BUY_ZERO = 'D', 'N', CAT_PR.CAN_BUY_ZERO) = 'Y', 'Y', 'N' ) as CATALOG_AVAILABLE
, CAT_PR.WEIGHT as CATALOG_WEIGHT
, CAT_VAT.RATE as CATALOG_VAT
, CAT_PR.VAT_INCLUDED as CATALOG_VAT_INCLUDED
, CAT_PR.PRICE_TYPE as CATALOG_PRICE_TYPE
, CAT_PR.RECUR_SCHEME_TYPE as CATALOG_RECUR_SCHEME_TYPE
, CAT_PR.RECUR_SCHEME_LENGTH as CATALOG_RECUR_SCHEME_LENGTH
, CAT_PR.TRIAL_PRICE_ID as CATALOG_TRIAL_PRICE_ID
, CAT_PR.WITHOUT_ORDER as CATALOG_WITHOUT_ORDER
, CAT_PR.SELECT_BEST_PRICE as CATALOG_SELECT_BEST_PRICE
, CAT_PR.PURCHASING_PRICE as CATALOG_PURCHASING_PRICE
, CAT_PR.PURCHASING_CURRENCY as CATALOG_PURCHASING_CURRENCY
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_element_prop_s10 FPS0 ON FPS0.IBLOCK_ELEMENT_ID = BE.ID
INNER JOIN b_iblock_property FP0 ON FP0.IBLOCK_ID = B.ID AND FP0.CODE='PURPOSE'
INNER JOIN b_iblock_property FP1 ON FP1.IBLOCK_ID = B.ID AND FP1.CODE='SPHERE'
INNER JOIN b_iblock_property FP2 ON FP2.IBLOCK_ID = B.ID AND FP2.CODE='KIND'
INNER JOIN b_iblock_property FP3 ON FP3.IBLOCK_ID = B.ID AND FP3.CODE='MATERIAL'
INNER JOIN b_iblock_property FP4 ON FP4.IBLOCK_ID = B.ID AND FP4.CODE='SURFACE'
INNER JOIN b_iblock_element_prop_m10 FPV0 ON FPV0.IBLOCK_PROPERTY_ID = FP0.ID AND FPV0.IBLOCK_ELEMENT_ID = BE.ID
INNER JOIN b_iblock_element_prop_m10 FPV1 ON FPV1.IBLOCK_PROPERTY_ID = FP1.ID AND FPV1.IBLOCK_ELEMENT_ID = BE.ID
INNER JOIN b_iblock_element_prop_m10 FPV2 ON FPV2.IBLOCK_PROPERTY_ID = FP2.ID AND FPV2.IBLOCK_ELEMENT_ID = BE.ID
INNER JOIN b_iblock_element_prop_m10 FPV3 ON FPV3.IBLOCK_PROPERTY_ID = FP3.ID AND FPV3.IBLOCK_ELEMENT_ID = BE.ID
INNER JOIN b_iblock_element_prop_m10 FPV4 ON FPV4.IBLOCK_PROPERTY_ID = FP4.ID AND FPV4.IBLOCK_ELEMENT_ID = BE.ID
LEFT JOIN b_catalog_price CAT_P4 ON (CAT_P4.PRODUCT_ID = BE.ID AND CAT_P4.CATALOG_GROUP_ID = 4) AND ((CAT_P4.QUANTITY_FROM <= 1 OR CAT_P4.QUANTITY_FROM IS NULL) AND (CAT_P4.QUANTITY_TO >= 1 OR CAT_P4.QUANTITY_TO IS NULL))
LEFT JOIN b_catalog_product CAT_PR ON (CAT_PR.ID = BE.ID)
LEFT JOIN b_catalog_iblock CAT_IB ON ((CAT_PR.VAT_ID IS NULL OR CAT_PR.VAT_ID = 0) AND CAT_IB.IBLOCK_ID = BE.IBLOCK_ID)
LEFT JOIN b_catalog_vat CAT_VAT ON (CAT_VAT.ID = IF((CAT_PR.VAT_ID IS NULL OR CAT_PR.VAT_ID = 0), CAT_IB.VAT_ID, CAT_PR.VAT_ID))
WHERE
1=1 AND ( ((((BE.IBLOCK_ID = '10')))) AND (EXISTS ( SELECT IBLOCK_ID
FROM
b_iblock_site
WHERE
IBLOCK_ID = B.ID
AND (((SITE_ID='s1'))) )) AND ((((B.ACTIVE='Y')))) 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 ( 1=1 ) AND ((((FPV0.VALUE_ENUM = '1075')))) AND ((((FPV1.VALUE_ENUM = '1073')))) AND ((((FPV2.VALUE_ENUM = '1084')))) AND ((((FPV3.VALUE_ENUM = '2808')))) AND ((((FPV4.VALUE_ENUM = '1070')))) ) AND (((BE.WF_STATUS_ID=1
AND BE.WF_PARENT_ELEMENT_ID IS NULL)))
ORDER BY
BE.NAME asc ,BE.ID desc
LIMIT 0, 12
Фильтруемые свойства типа список. В каталоге 2 тыс. товаров. Помимо свойств для фильтра в инфоблок каталога выгружаются еще другие свойства из 1С, всего свойств около 120. Но фильтровать надо только по 8-10 свойствам.
Значения свойств хранятся в отдельной таблице. Оценка производительности по операциям с базой выше эталона.
Вопрос: можно ли сократить время запросов? Как можно оптимизировать фильтрацию? Или при работе через API не избежать кучи джоинов в запросах и такого времени исполнения? Почему при фильтрации по 4м и 5ти параметрам такая большая разница во времени выполнения запроса?