הפילטר החכם מתחיל לאבד ביצועים כאשר הקטלוג עולה על 5,000 פריטים. ב-50,000+ פריטים, זה יכול לקחת 5–15 שניות בבקשה הראשונה ו-1–3 שניות עם קאש. נשמע מוכר? כמפתחי ביטריקס עם ניסיון של 7+ שנים, נתקלנו בזה עשרות פעמים. עם 150+ פרויקטים מאחורינו, אנחנו מבטיחים תוצאות: הפחתת TTFB עד 200 אלפיות השנייה. זו לא בעיה של אלגוריתם — זו תוצאה של חישוב מחדש של מוני ערכים לכל מאפיין בכל בקשה. בפרויקט אמיתי עם 30 מאפיינים ו-50,000 מוצרים, זה אומר אלפי שאילתות מסד נתונים לכל קריאה בודדת.
איך הפילטר החכם עובד מתחת למכסה המנוע
רכיב ה-bitrix:catalog.smart.filter יוצר טופס עם טעינת תוצאות אסינכרונית דרך AJAX. צרכני המשאבים העיקריים הם שאילתות COUNT עבור כל ערך מאפיין. ללא אופטימיזציה, בקשה אחת לפילטר יכולה לגרום ליותר מ-200 פגיעות במסד הנתונים. ניתן לקרוא עוד על הפלטפורמה בוויקיפדיה.
איך לאבחן את הבעיה
השלב הראשון הוא מדידה, לא ניחושים. הפעל פרופילינג של SQL:
// В начале скрипта
define('LOG_FILENAME', $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/log_filter.php');
$GLOBALS['DB']->ShowSqlStat = 'Y';
// После отработки компонента фильтра
$sqlLog = $GLOBALS['DB']->GetSqlTrack();
// Смотрим самые медленные запросы
usort($sqlLog, fn($a, $b) => $b['time'] <=> $a['time']);
var_dump(array_slice($sqlLog, 0, 10));
תמונה אופיינית: 80% מהזמן מושקע על שאילתות COUNT לחישוב מחדש של מספר המוצרים לכל ערך מאפיין עם הפילטר המופעל. להבנה מעמיקה של אינדוקסים ב-MySQL, אני ממליץ על התיעוד.
למה אינדוקסים הם קריטיים
השיפור המשמעותי ביותר ללא שינויי קוד הוא אינדוקסים נכונים. הפילטר החכם עושה שימוש נרחב בטבלאות // В начале скрипта define('LOG_FILENAME', $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/log_filter.php'); $GLOBALS['DB']->ShowSqlStat = 'Y'; // После отработки компонента фильтра $sqlLog = $GLOBALS['DB']->GetSqlTrack(); // Смотрим самые медленные запросы usort($sqlLog, fn($a, $b) => $b['time'] <=> $a['time']); var_dump(array_slice($sqlLog, 0, 10)); (מאפיינים פשוטים) ו-b_iblock_element_prop_s* (מאפיינים מרובים).
-- Проверка существующих индексов
SHOW INDEX FROM b_iblock_element_prop_s15;
-- 15 = ID инфоблока
-- Добавление составного индекса для фильтрации
CREATE INDEX idx_filter_prop ON b_iblock_element_prop_s15 (IBLOCK_ELEMENT_ID, PROPERTY_186, PROPERTY_187);
-- Для таблицы множественных свойств
CREATE INDEX idx_mult_prop ON b_iblock_element_property (IBLOCK_ELEMENT_ID, IBLOCK_PROPERTY_ID, VALUE_ENUM, VALUE_NUM);לאחר הוספת אינדוקסים, זמן התגובה בקטלוג של 30,000 פריטים יורד פי 2–4 ללא כל שינוי בקוד. השווה בין גישות:
| גישה | זמן בקשה ראשונה | זמן קאש | מורכבות |
|---|---|---|---|
| ללא אופטימיזציה | 8–15 שניות | 2–3 שניות | — |
| אינדוקסים בלבד | 1–2 שניות | 0.5 שניות | נמוכה |
| אינדוקסים + טעינה עצלה | 0.2 שניות (TTFB) | 0.3 שניות (מונים) | בינונית |
| אינדוקסים + צבירה מוקדמת | 0.15 שניות | 0.15 שניות | גבוהה |
הערה: צבירה מוקדמת נותנת רווח של פי 50 בהשוואה לשאילתות חיות בקטלוג של 150,000 פריטים.
איך להגדיר קאש לפילטר
$APPLICATION->IncludeComponent('bitrix:catalog.smart.filter', 'my_filter', [
'IBLOCK_ID' => 15,
'SMART_FILTER' => 'Y',
'CACHE_TYPE' => 'A', // авто
'CACHE_TIME' => 3600, // 1 час
'CACHE_GROUPS' => 'N', // не разделять кеш по группам пользователей
'LAZY_LOAD' => 'Y', // ленивая загрузка счётчиков
]);b_iblock_element_prop_m* — המונים נטענים דרך בקשת AJAX נפרדת לאחר רינדור העמוד. העמוד מגיב מהר, המונים מופיעים תוך 200–400 אלפיות השנייה.
קאש עם תגי invalidation
קאש אגרסיבי עם invalidation כאשר הקטלוג משתנה:
// Тег кеша привязан к инфоблоку
$taggedCache = \Bitrix\Main\Data\TaggedCache::instance();
$taggedCache->startTagCache('/catalog/filter/');
// Выполняем работу фильтра
// ...
$taggedCache->registerTag('iblock_id_' . CATALOG_IBLOCK_ID);
$taggedCache->endTagCache();
// При изменении элементов инфоблока — автоинвалидация:
// AddEventHandler('iblock', 'OnAfterIBlockElementUpdate', function($id, $fields) {
// \Bitrix\Main\Data\TaggedCache::instance()->clearByTag('iblock_id_' . $fields['IBLOCK_ID']);
// });
מה נותנת צבירה מוקדמת של מונים
עבור קטלוגים עם 100,000+ פריטים — צבירה מוקדמת לטבלה נפרדת דרך סוכן:
קוד סוכן לצבירה מוקדמת
// Таблица для хранения предагрегированных данных
// CREATE TABLE b_custom_filter_counts (
// iblock_id INT, property_code VARCHAR(50),
// property_value VARCHAR(255), cnt INT,
// updated_at DATETIME,
// PRIMARY KEY (iblock_id, property_code, property_value(100))
// );
class FilterCountsAgent {
public static function recalculate(): string {
$iblockId = CATALOG_IBLOCK_ID;
$propertyCodes = ['BRAND', 'MATERIAL', 'COUNTRY'];
foreach ($propertyCodes as $code) {
// Подсчёт через прямой SQL
$sql = "
INSERT INTO b_custom_filter_counts (iblock_id, property_code, property_value, cnt, updated_at)
SELECT e.IBLOCK_ID, p.CODE, pv.VALUE, COUNT(DISTINCT e.ID), NOW()
FROM b_iblock_element e
INNER JOIN b_iblock_element_property ep ON ep.IBLOCK_ELEMENT_ID = e.ID
INNER JOIN b_iblock_property p ON p.ID = ep.IBLOCK_PROPERTY_ID
INNER JOIN b_iblock_property_enum pv ON pv.ID = ep.VALUE_ENUM
WHERE e.IBLOCK_ID = {$iblockId} AND e.ACTIVE = 'Y' AND p.CODE = '{$code}'
GROUP BY e.IBLOCK_ID, p.CODE, pv.VALUE
ON DUPLICATE KEY UPDATE cnt = VALUES(cnt), updated_at = VALUES(updated_at)
";
\Bitrix\Main\Application::getConnection()->query($sql);
}
return 'FilterCountsAgent::recalculate();';
}
}הסוכן רץ כל 15–30 דקות. המונים בממשק המשתמש נשלפים מהטבלה הזו — לא משאילתות חיות.
הפחתת מספר המאפיינים בפילטר
לעתים קרובות 30–40% מהמאפיינים בפילטר אף פעם לא בשימוש. נתח נתונים ממערכות אנליטיקה:
- הגדר אירועי GTM על אינטראקציות עם כל בלוק פילטר
- במשך 30 יום, קבע בלוקים בשימוש לעומת לא בשימוש
- הסר בלוקים עם פחות מ-2% אינטראקציה
בפועל, לאחר ביקורת כזו, קטלוג עם 28 מאפיינים בפילטר מסיים עם 12–15. זמן יצירת העמוד יורד ב-35–60% ללא שינויים טכניים.
מהניסיון שלנו: מרקטפלייס עם 80,000 פריטים
מרקטפלייס לחומרי בניין. הפילטר הגיב ב-8–12 שניות בבקשה הראשונה, 2–3 שניות עם קאש. אינדקס הקאש אופס בכל פעם שספק שינה מחיר (עשרות פעמים ביום).
הפתרון בשלושה שלבים:
- הוספנו אינדוקסים מורכבים על טבלאות המאפיינים — הזמן ירד ל-1.8 שניות ללא קאש
- צבירה מוקדמת של מונים דרך סוכן כל 20 דקות — מונים מהטבלה ב-5 אלפיות השנייה
- טעינה עצלה של מונים — הבייט הראשון של העמוד ב-180 אלפיות השנייה, מונים ב-300 אלפיות השנייה
תוצאה: מ-8–12 שניות ל-180 אלפיות השנייה TTFB, מונים ב-300 אלפיות השנייה.
מה כלול בעבודת האופטימיזציה?
- ביקורת על תצורת הפילטר הנוכחית ופרופילינג של SQL
- יצירה ואופטימיזציה של אינדוקסים לטבלאות המאפיינים
- הגדרת קאש (מתויג, טעינה עצלה)
- צבירה מוקדמת של מונים (במידת הצורך)
- המלצות להפחתת מאפיינים לא בשימוש
- תיעוד ליישום ותמיכה
- ייעוץ עם הצוות שלך לפיתוח עתידי
לוח זמנים ואיך להתחיל
ביקורת, הוספת אינדוקסים והגדרת קאש — 1–2 ימי עסקים. אופטימיזציה מלאה עם צבירה מוקדמת, טעינה עצלה וביקורת מאפיינים לא בשימוש — 3–5 ימי עסקים.
נעריך את הפרויקט שלך תוך יום אחד. הזמן ביקורת פילטר — קבל תוכנית אופטימיזציה. צור קשר כדי לדון בפרטים. השאר בקשה לייעוץ — ננתח את הקטלוג שלך.

