У меня есть вызов CakePHP 3 find()
, который Я некоторое время пытался оптимизировать .Я сузил его до этих двух фрагментов, с той лишь разницей, что удален параметр contain
.Время измерялось с помощью DebugKit .
Включая contain
:
public function qrytest() {
$table = TableRegistry::get('OrderOptions', array(
'className' => 'App\Model\Table\Opencart\OrderOptionsTable',
));
$results = $table->find('all', array(
'fields' => array(
'OrderOptions.order_product_id',
'OrderOptions.order_option_id',
'OrderOptions.value',
),
'conditions' => array(
'OrderOptions.order_id' => 123,
),
'contain' => array(
'OpencartProductOptions' => array(
'OpencartOption',
),
'OpencartOrderProducts' => array(
'OpencartOrders' => array(
'OpencartShippingZone',
),
'OpencartProduct' => array(
'OpencartWeightClass',
),
),
'OpencartProductOptionValues',
),
))->all();
$this->viewBuilder()->template('anEmptyView');
}
Sql Log : 1/99 мс; Таймер : 4,42 с / 5,72 МБ
Нет contain
public function qrytest() {
$table = TableRegistry::get('OrderOptions', array(
'className' => 'App\Model\Table\Opencart\OrderOptionsTable',
));
$results = $table->find('all', array(
'fields' => array(
'OrderOptions.order_product_id',
'OrderOptions.order_option_id',
'OrderOptions.value',
),
'conditions' => array(
'OrderOptions.order_id' => 123,
),
// contain parameter removed; nothing else changed
))->all();
$this->viewBuilder()->template('anEmptyView');
}
Sql Log : 1/92 мс; Таймер : 1,06 с / 4,83 МБ
Сводка : включение параметра содержит заставляет контроллер визуализироваться почти 5 секунд, не изменяя фактический запросвремя значительно.Расширение вкладки Таймеров DebugKit показывает Действие контроллера: 4 388,74 мс (снимки экрана часть 1 , часть 2 )
Первое, что приходит на ум, это оптимизация объединений и индексов, но если вы посмотрите на результаты выше, сам запрос, по-видимому, занимает одинаковое количество времени в обоих случаях.Для подтверждения я выполнил исходный запрос (включая JOIN) непосредственно в MySQL Workbench , и это занимает около 100 мс, что соответствует тому, что я вижу в выводе DebugKit.Кроме того, я действительно все-таки создал все необходимые индексы некоторое время назад.
Тем не менее, я начинаю думать, что проблема не в моем запросе MySQL, а в том, как CakePHP его обрабатывает, и здесь мне нужна помощь.
Я могуопубликовать информацию о структуре таблицы, если вам нужно.
Обновления
- Нет разницы между включенной и выключенной гидратацией.Попробовал
$query->enableHydration(false);
и $query->hydrate(false);
(согласно query-builder.html # receive-arrays-вместо-entity-* ) - Отключил отладку, явно указав
'debug' => false
, по-прежнемумедленно: время = 4.30 с, измеренное браузером Вот сгенерированный запрос:
SELECT
`OrderOptions`.`order_product_id` AS `OrderOptions__order_product_id`,
`OrderOptions`.`order_option_id` AS `OrderOptions__order_option_id`,
`OrderOptions`.`value` AS `OrderOptions__value`
FROM
`order_option` `OrderOptions`
LEFT JOIN `product_option` `OpencartProductOptions` ON `OpencartProductOptions`.`product_option_id` = (
`OrderOptions`.`product_option_id`
)
LEFT JOIN `option` `OpencartOption` ON `OpencartOption`.`option_id` = (
`OpencartProductOptions`.`option_id`
)
LEFT JOIN `order_product` `OpencartOrderProducts` ON `OpencartOrderProducts`.`order_product_id` = (
`OrderOptions`.`order_product_id`
)
LEFT JOIN `order` `OpencartOrders` ON `OpencartOrders`.`order_id` = (
`OpencartOrderProducts`.`order_id`
)
LEFT JOIN `zone` `OpencartShippingZone` ON `OpencartShippingZone`.`zone_id` = (
`OpencartOrders`.`shipping_zone_id`
)
LEFT JOIN `product` `OpencartProduct` ON `OpencartProduct`.`product_id` = (
`OpencartOrderProducts`.`product_id`
)
LEFT JOIN `weight_class` `OpencartWeightClass` ON `OpencartProduct`.`weight_class_id` = (
`OpencartWeightClass`.`weight_class_id`
)
LEFT JOIN `product_option_value` `OpencartProductOptionValues` ON `OpencartProductOptionValues`.`product_option_value_id` = (
`OrderOptions`.`product_option_value_id`
)
WHERE
`OrderOptions`.`order_id` = 123
Вот вывод XDebug: