Оптимизация SQL-запросов — один из главных инструментов ускорения Битрикс при высоких нагрузках. D7 ORM удобен, но неправильное использование создаёт медленные запросы.
Включение профилировщика
// В local/php_interface/init.php (только на dev!)
define("SHOW_SQL_STAT", true);
В низу страницы появится список всех SQL-запросов с временем выполнения.
N+1 запросы — главная проблема
// ПЛОХО: N+1 запросов
$items = ElementTable::getList(['select' => ['ID']]);
foreach ($items as $item) {
$props = PropertyTable::getList(['filter' => ['ELEMENT_ID' => $item['ID']]]);
}
// ХОРОШО: один запрос с JOIN через runtime reference
$items = ElementTable::getList([
'select' => ['ID', 'NAME', 'PROP_VALUE' => 'PROPERTY.VALUE'],
'runtime' => [
new ORMFieldsRelationsReference(
'PROPERTY',
PropertyTable::class,
['=this.ID' => 'ref.ELEMENT_ID']
),
],
]);
Индексы — быстрая оптимизация
EXPLAIN SELECT * FROM b_iblock_element WHERE IBLOCK_ID=5 AND ACTIVE='Y';
Если в EXPLAIN видите type: ALL — нет подходящего индекса. Добавьте:
ALTER TABLE b_iblock_element ADD INDEX idx_iblock_active (IBLOCK_ID, ACTIVE);
Кэширование результатов
$cache = Cache::createInstance();
$cacheId = md5(serialize($filter));
if ($cache->initCache(3600, $cacheId, '/my/cache/')) {
$data = $cache->getVars();
} else {
$cache->startDataCache();
$data = UserTable::getList(['filter' => $filter])->fetchAll();
$cache->endDataCache($data);
}
Всегда выбирайте только нужные поля
// Вместо выборки всех полей
$result = ProductTable::getList([
'select' => ['ID', 'NAME', 'PRICE'],
'filter' => ['=ACTIVE' => 'Y'],
'limit' => 20,
'offset' => ($page - 1) * 20,
]);
