אופטימיזציה של שאילתות אינפובלוקים ב-1C-Bitrix: האצת הקטלוג שלך
הבעיה האמיתית: שאילתות אינפובלוק איטיות
לעתים קרובות אנו נתקלים בפרויקטים שבהם הקטלוג של Bitrix מאט עקב שאילתות אינפובלוק לא אופטימליות. תרחיש טיפוסי: דף רשימת מוצרים עם 48 פריטים לוקח 2-3 שניות לטעון, גם כאשר שרת MySQL אינו עמוס. ה-CIBlockElement::GetList הסטנדרטי עם סינון מאפיינים יוצר מספר JOINים, ועם 100 מוצרים שיש לכל אחד 5 מאפיינים, EXPLAIN מראה סריקות של מאות אלפי שורות. TTFB עולה על שנייה אחת גם ב-VPS עם 4 vCPUs. הפלטפורמה 1C-Bitrix היא אחת ממערכות ניהול התוכן הפופולריות למסחר אלקטרוני, אך האינפובלוקים שלה הופכים לעתים קרובות לצוואר בקבוק. בניסיון שלנו, עם למעלה מ-50 פרויקטים שעברו אופטימיזציה, 90% מהבעיות נפתרות על ידי מעבר ל-D7 ORM והצבה נכונה של אינדקסים. זה מפחית את עלויות משאבי השרת ונשאר במסגרת התקציב ללא השקעה נוספת. אנו מבטיחים הפחתה של פי 3-5 בזמן השאילתה. מאמר זה הוא תוצאה של שנות הניסיון שלנו.
מדוע שאילתות Bitrix סטנדרטיות איטיות?
ה-API הישן CIBlockElement::GetList בעת שימוש במסנן PROPERTY_* מוסיף JOIN עבור כל מאפיין. אם יש 5 מאפיינים במסנן — 5 JOINים. תוכנית השאילתה הופכת ללא אופטימלית, במיוחד כאשר טבלת b_iblock_element_property מכילה מיליוני שורות. בנוסף, הפרמטר arSelect עם "*" או ללא רשימה מפורשת מאלץ את ה-API לשלוף את כל השדות, כולל טקסטים ארוכים כמו PREVIEW_TEXT ו-DETAIL_TEXT. כתוצאה מכך, נפח הנתונים ממסד הנתונים גדל פי 3-5.
טעות נפוצה נוספת היא בעיית שאילתות N+1. לאחר שליפת רשימת פריטים, מפתחים קוראים לעתים קרובות ל-CIBlockElement::GetProperty() עבור כל מוצר בלולאה. עבור 48 מוצרים, זה 1 + 48 = 49 שאילתות. זמן הביצוע גדל באופן ליניארי.
כיצד ליישם שליפה בקבוצות ללא רגרסיה?
מעבר ל-\Bitrix\Iblock\ElementTable מ-D7 ORM נותן שליטה מלאה על SQL. ניתן לאמת כל שאילתה באמצעות getQuery()->getSql() לפני הביצוע. דוגמה לשאילתה אופטימלית לדף קטלוג:
use Bitrix\Iblock\ElementTable;
$result = ElementTable::getList([
'select' => [
'ID',
'NAME',
'CODE',
'PREVIEW_PICTURE',
'IBLOCK_SECTION_ID',
],
'filter' => [
'=IBLOCK_ID' => CATALOG_IBLOCK_ID,
'=ACTIVE' => 'Y',
'=IBLOCK_SECTION_ID' => $sectionId,
],
'order' => ['SORT' => 'ASC', 'ID' => 'ASC'],
'limit' => 24,
'offset' => $page * 24,
'cache' => ['ttl' => 3600],
]);
use Bitrix\Iblock\ElementTable; $result = ElementTable::getList([ 'select' => [ 'ID', 'NAME', 'CODE', 'PREVIEW_PICTURE', 'IBLOCK_SECTION_ID', ], 'filter' => [ '=IBLOCK_ID' => CATALOG_IBLOCK_ID, '=ACTIVE' => 'Y', '=IBLOCK_SECTION_ID' => $sectionId, ], 'order' => ['SORT' => 'ASC', 'ID' => 'ASC'], 'limit' => 24, 'offset' => $page * 24, 'cache' => ['ttl' => 3600], ]); מפורש ללא מאפיינים — השאילתה נוגעת רק ב-select, ללא JOINים. אם יש צורך בערכי מאפיינים עבור מספר מוצרים, אנו משתמשים בשליפה בקבוצות לפי מזהים:
$ids = array_column($elements, 'ID');
$propsResult = \CIBlockElement::GetPropertyValuesArray(
$ids,
CATALOG_IBLOCK_ID,
['CODE' => ['BRAND', 'COLOR', 'SIZE']]
);תבנית זו של "שליפה לפי מזהה בקבוצות" פותרת את בעיית N+1. התיעוד הרשמי על D7 ORM מכיל את כל הפרטים. אקדמיית 1C-Bitrix
מקרה מבחן מהניסיון שלנו: קטלוג חומרי בניין עם 45,000 פריטים
עבדנו עם לקוח — חנות מקוונת לחומרי בניין. הקטלוג הכיל 45,000 פריטים פעילים. דף קטגוריה עם 48 מוצרים נטען ב-1.8 שניות ללא מטמון. יומן השאילתות האיטיות של MySQL חשף מספר בעיות:
-
b_iblock_elementעם$ids = array_column($elements, 'ID'); $propsResult = \CIBlockElement::GetPropertyValuesArray( $ids, CATALOG_IBLOCK_ID, ['CODE' => ['BRAND', 'COLOR', 'SIZE']] );ו-CIBlockElement::GetListעל 5 מאפיינים לקח 640 אלפיות השנייה לשאילתה. - בלוק "מוצרים קשורים" ביצע שאילתה נפרדת עבור כל אחד מ-6 הפריטים (N+1).
- שאילתת עץ הקטגוריות לא כללה הגבלת עומק.
ביצענו את הפעולות הבאות:
- שכתבנו את השאילתה הראשית ל-D7, והשארנו רק 8 שדות נחוצים.
- החלפנו שאילתות מאפיינים איטרטיביות בשליפה בקבוצות באמצעות
SELECT => "*". - הגבלנו את
PROPERTY_FILTERבשליפת הקטגוריות והוספנו מטמון מתויג. - יצרנו אינדקס מורכב על
GetPropertyValuesArray:
ALTER TABLE b_iblock_element ADD INDEX idx_iblock_section_active_sort (IBLOCK_ID, IBLOCK_SECTION_ID, ACTIVE, SORT); תוצאה: TTFB של דף הקטגוריה ללא מטמון ירד מ-1.8 שניות ל-380 אלפיות השנייה, ועם מטמון — ל-45 אלפיות השנייה. מספר שאילתות מסד הנתונים ירד מ-12 ל-4. עומס MySQL ירד פי 3, וחסך ללקוח עד 30% בעלויות השרת. הלקוח קיבל יכולת לשרת יותר מבקרים ללא הגדלת הוצאות.
השוואה בין הגישה הישנה לחדשה
| פרמטר | CIBlockElement::GetList | D7 ORM + קבוצות |
|---|---|---|
| מספר JOINים בסינון לפי 5 מאפיינים | 5 | 0 (אם מאפיינים לא ב-select) |
| שליטה ב-SQL | לא | מלאה (getQuery()->getSql()) |
| סיכון N+1 | גבוה | מבוטל על ידי שליפה בקבוצות |
| מטמון | רק מבוסס קבצים | מתויג + מטמון נתונים |
| ביצועים (דוגמה) | 640 אלפיות השנייה | 80 אלפיות השנייה |
ה-API של D7 מהיר פי 3-5 עבור שאילתות טיפוסיות.
מה כלול בעבודת האופטימיזציה
אנו מציעים אופטימיזציה מקיפה של שאילתות אינפובלוק במפתח מלא. העבודה כוללת:
- ניתוח יומן השאילתות האיטיות של MySQL ולוח הביצועים של Bitrix.
- ביקורת על כל הרכיבים המותאמים אישית עבור N+1 ושליפות לא אופטימליות.
- שכתוב שאילתות קריטיות ל-D7 ORM עם select מפורש ואסטרטגיות קבוצות.
- הוספת אינדקסים מורכבים נחוצים והגדרת מטמון מתויג.
- יצירת תיעוד לשאילתות האופטימליות עבור הצוות שלך.
- הכשרת מפתחים על D7 ושיטות עבודה מומלצות.
מידע נוסף על הניסיון שלנו
אנו עוסקים בפיתוח Bitrix למעלה מ-10 שנים, מוסמכים על ידי 1C-Bitrix. אופטימיזציה מוצלחת של קטלוגים עבור 20+ פרויקטים גדולים עם תעבורה של 10,000 מבקרים ביום.לוחות זמנים ומחירים
| שלב | משך |
|---|---|
| ביקורת שאילתות (יומן איטי, Explain, לוח Bitrix) | 1–2 ימים |
| שכתוב שאילתות קריטיות (D7, קבוצות) | 3–7 ימים |
| הגדרת אינדקסים ומטמון | 1–2 ימים |
| תיעוד והכשרה | יום אחד |
המחיר מחושב באופן אישי לפי גודל הקטלוג ומספר הרכיבים. צור קשר להערכת הפרויקט שלך — זה לוקח יומיים. קבל ייעוץ לגבי האצת הקטלוג שלך.

