雄辩的查询生成器很慢

时间:2017-10-05 14:41:20

标签: mysql laravel eloquent laravel-5.4

我正在做一个执行各种事情的ajax请求,并且它需要永远加载。在进行了一些挖掘以找出瓶颈所在之后,我发现使用Eloquent构建查询的速度非常慢。

这是我正在构建的原始查询:

SELECT
  `events`.`id`,
  FROM_UNIXTIME(
    EVENTS.event_datetime,
    "%a %D %b %H:%i"
  ) AS DATETIME,
  CONCAT(
    countries.name,
    " ",
    leagues.name
  ) AS countryleague,
  CONCAT(
    EVENTS.team1_name,
    " vs ",
    EVENTS.team2_name
  ) AS game,
  CONCAT(
    eo1.value,
    " <a href=\"#\" class=\"add-bet\" data-id=\"",
    eo1.id,
    "\"><i class=\"fa fa-plus\"></i></a>"
  ) AS home,
  CONCAT(
    eo2.value,
    " <a href=\"#\" class=\"add-bet\" data-id=\"",
    eo2.id,
    "\"><i class=\"fa fa-plus\"></i></a>"
  ) AS draw,
  CONCAT(
    eo3.value,
    " <a href=\"#\" class=\"add-bet\" data-id=\"",
    eo3.id,
    "\"><i class=\"fa fa-plus\"></i></a>"
  ) AS away,
  CONCAT(
    eo4.value,
    " <a href=\"#\" class=\"add-bet\" data-id=\"",
    eo4.id,
    "\"><i class=\"fa fa-plus\"></i></a>"
  ) AS over,
  CONCAT(
    eo5.value,
    " <a href=\"#\" class=\"add-bet\" data-id=\"",
    eo5.id,
    "\"><i class=\"fa fa-plus\"></i></a>"
  ) AS under,
  CONCAT(
    "<a href=\"#\" class=\"expand-all btn\" data-id=\"",
    EVENTS.id,
    "\"><i class=\"fa fa-plus\"></i> Expand all odds</a>"
  ) AS expand,
  `leagues`.`major`,
  `leagues`.`name` AS `league`
FROM
  `events`
INNER JOIN
  `countries` ON `events`.`country_id` = `countries`.`id` AND `countries`.`id` IN(1)
INNER JOIN
  `leagues` ON `events`.`league_id` = `leagues`.`id` AND `leagues`.`id` IN(1,
  50)
LEFT JOIN
  `event_odds` AS `eo1` ON `events`.`id` = `eo1`.`event_id` AND `eo1`.`market_id` = 3 AND `eo1`.`market_value_id` = 1 AND `eo1`.`bookmaker_id` IN(1,
  2,
  24) AND `eo1`.`value` = `eo1`.`best_odd`
LEFT JOIN
  `event_odds` AS `eo2` ON `events`.`id` = `eo2`.`event_id` AND `eo2`.`market_id` = 3 AND `eo2`.`market_value_id` = 2 AND `eo2`.`bookmaker_id` IN(1,
  2,
  24) AND `eo2`.`value` = `eo2`.`best_odd`
LEFT JOIN
  `event_odds` AS `eo3` ON `events`.`id` = `eo3`.`event_id` AND `eo3`.`market_id` = 3 AND `eo3`.`market_value_id` = 3 AND `eo3`.`bookmaker_id` IN(1,
  2,
  24) AND `eo3`.`value` = `eo3`.`best_odd`
LEFT JOIN
  `event_odds` AS `eo4` ON `events`.`id` = `eo4`.`event_id` AND `eo4`.`market_id` = 4 AND `eo4`.`market_value_id` = 49 AND `eo4`.`bookmaker_id` IN(1,
  2,
  24) AND `eo4`.`value` = `eo4`.`best_odd`
LEFT JOIN
  `event_odds` AS `eo5` ON `events`.`id` = `eo5`.`event_id` AND `eo5`.`market_id` = 4 AND `eo5`.`market_value_id` = 50 AND `eo5`.`bookmaker_id` IN(1,
  2,
  24) AND `eo5`.`value` = `eo5`.`best_odd`
WHERE
  `events`.`sport_id` IN(1) AND `events`.`event_datetime` > 1507204934
GROUP BY
  `events`.`id`
ORDER BY
  `leagues`.`major` DESC,
  `leagues`.`name` ASC,
  `events`.`event_datetime` ASC
LIMIT 50 OFFSET 0

我正在以雄辩的方式建造它:

$query = Event_model::join('countries', function($q) use ($enabled_country_ids) {
    $q->on('events.country_id', '=', 'countries.id')
      ->whereIn('countries.id', $enabled_country_ids);
})
->join('leagues', function($q) use ($enabled_league_ids) {
    $q->on('events.league_id', '=', 'leagues.id')
      ->whereIn('leagues.id', $enabled_league_ids); 
})
->leftJoin('event_odds AS eo1', function($q) use($win_market, $home_market_value, $enabled_bookmaker_ids) {
    $q->on('events.id', '=', 'eo1.event_id')
      ->where('eo1.market_id', '=', $win_market->id)
      ->where('eo1.market_value_id', '=', $home_market_value->id)
      ->whereIn('eo1.bookmaker_id', $enabled_bookmaker_ids)
      ->on('eo1.value', '=', 'eo1.best_odd');
})
->leftJoin('event_odds AS eo2', function($q) use($win_market, $draw_market_value, $enabled_bookmaker_ids) {
    $q->on('events.id', '=', 'eo2.event_id')
      ->where('eo2.market_id', '=', $win_market->id)
      ->where('eo2.market_value_id', '=', $draw_market_value->id)
      ->whereIn('eo2.bookmaker_id', $enabled_bookmaker_ids)
      ->on('eo2.value', '=', 'eo2.best_odd');
})
->leftJoin('event_odds AS eo3', function($q) use($win_market, $away_market_value, $enabled_bookmaker_ids) {
    $q->on('events.id', '=', 'eo3.event_id')
      ->where('eo3.market_id', '=', $win_market->id)
      ->where('eo3.market_value_id', '=', $away_market_value->id)
      ->whereIn('eo3.bookmaker_id', $enabled_bookmaker_ids)
      ->on('eo3.value', '=', 'eo3.best_odd');
})
->leftJoin('event_odds AS eo4', function($q) use($ou_market, $over_market_value, $enabled_bookmaker_ids) {
    $q->on('events.id', '=', 'eo4.event_id')
      ->where('eo4.market_id', '=', $ou_market->id)
      ->where('eo4.market_value_id', '=', $over_market_value->id)
      ->whereIn('eo4.bookmaker_id', $enabled_bookmaker_ids)
      ->on('eo4.value', '=', 'eo4.best_odd');
})
->leftJoin('event_odds AS eo5', function($q) use($ou_market, $under_market_value, $enabled_bookmaker_ids) {
    $q->on('events.id', '=', 'eo5.event_id')
      ->where('eo5.market_id', '=', $ou_market->id)
      ->where('eo5.market_value_id', '=', $under_market_value->id)
      ->whereIn('eo5.bookmaker_id', $enabled_bookmaker_ids)
      ->on('eo5.value', '=', 'eo5.best_odd');
})
->whereIn('events.sport_id', $enabled_sports_ids)
->where('events.event_datetime', '>', time())
->groupBy('events.id')
->select([
    'events.id',
    DB::raw('FROM_UNIXTIME(events.event_datetime, "%a %D %b %H:%i") AS datetime'),
    DB::raw('CONCAT(countries.name, " ", leagues.name) AS countryleague'),
    DB::raw('CONCAT(events.team1_name, " vs ", events.team2_name) AS game'),
    DB::raw('CONCAT(eo1.value, " <a href=\"#\" class=\"add-bet\" data-id=\"", eo1.id, "\"><i class=\"fa fa-plus\"></i></a>") AS home'),           
    DB::raw('CONCAT(eo2.value, " <a href=\"#\" class=\"add-bet\" data-id=\"", eo2.id, "\"><i class=\"fa fa-plus\"></i></a>") AS draw'),
    DB::raw('CONCAT(eo3.value, " <a href=\"#\" class=\"add-bet\" data-id=\"", eo3.id, "\"><i class=\"fa fa-plus\"></i></a>") AS away'),
    DB::raw('CONCAT(eo4.value, " <a href=\"#\" class=\"add-bet\" data-id=\"", eo4.id, "\"><i class=\"fa fa-plus\"></i></a>") AS over'),
    DB::raw('CONCAT(eo5.value, " <a href=\"#\" class=\"add-bet\" data-id=\"", eo5.id, "\"><i class=\"fa fa-plus\"></i></a>") AS under'),
    DB::raw('CONCAT("<a href=\"#\" class=\"expand-all btn\" data-id=\"", events.id, "\"><i class=\"fa fa-plus\"></i> Expand all odds</a>") AS expand'),
    'leagues.major',
    'leagues.name AS league'
]);


if(!empty($order) && !$sort) {
    foreach($order as $order_info) {
        $query->orderBy($columns[$order_info['column']], $order_info['dir']);
    }
}

if($sort) {
    list($col, $order) = explode('|', $sort);
    $query->orderBy($col, $order);
    if($col=='countries.name') {
        $query->orderBy('events.event_datetime');
    }
}

if($league_id) {
    $query->where('events.league_id', '=', $league_id);
}

if($search['value']!='') {
    $query->where(function($q) use ($search) {
        $q->orWhere('events.team1_name', 'LIKE', "%".$search['value']."%")
          ->orWhere('events.team2_name', 'LIKE', "%".$search['value']."%")
          ->orWhere('leagues.name', 'LIKE', "%".$search['value']."%");
    });
}

或者我可以将它构建为一个大字符串,而不是:

$query = '
SELECT 
    `events`.`id`, 
    FROM_UNIXTIME(events.event_datetime, "%a %D %b %H:%i") AS datetime, 
    CONCAT(countries.name, " ", leagues.name) AS countryleague, 
    CONCAT(events.team1_name, " vs ", events.team2_name) AS game, 
    CONCAT(eo1.value, " <a href=\"#\" class=\"add-bet\" data-id=\"", eo1.id, "\"><i class=\"fa fa-plus\"></i></a>") AS home, 
    CONCAT(eo2.value, " <a href=\"#\" class=\"add-bet\" data-id=\"", eo2.id, "\"><i class=\"fa fa-plus\"></i></a>") AS draw, 
    CONCAT(eo3.value, " <a href=\"#\" class=\"add-bet\" data-id=\"", eo3.id, "\"><i class=\"fa fa-plus\"></i></a>") AS away, 
    CONCAT(eo4.value, " <a href=\"#\" class=\"add-bet\" data-id=\"", eo4.id, "\"><i class=\"fa fa-plus\"></i></a>") AS over, 
    CONCAT(eo5.value, " <a href=\"#\" class=\"add-bet\" data-id=\"", eo5.id, "\"><i class=\"fa fa-plus\"></i></a>") AS under, 
    CONCAT("<a href=\"#\" class=\"expand-all btn\" data-id=\"", events.id, "\"><i class=\"fa fa-plus\"></i> Expand all odds</a>") AS expand, 
    `leagues`.`major`, 
    `leagues`.`name` AS `league` 
FROM `events` 
JOIN `countries` 
    ON `events`.`country_id` = `countries`.`id` 
    AND `countries`.`id` IN ('.implode(',', $enabled_country_ids).') 
JOIN `leagues` 
    ON `events`.`league_id` = `leagues`.`id` 
    AND `leagues`.`id` IN ('.implode(',', $enabled_league_ids).') 
LEFT JOIN `event_odds` AS `eo1` 
    ON `events`.`id` = `eo1`.`event_id` 
    AND `eo1`.`market_id` = '.$win_market->id.' 
    AND `eo1`.`market_value_id` = '.$home_market_value->id.' 
    AND `eo1`.`bookmaker_id` IN('.implode(',', $enabled_bookmaker_ids).') 
    AND `eo1`.`value` = `eo1`.`best_odd` 
LEFT JOIN `event_odds` AS `eo2` 
    ON `events`.`id` = `eo2`.`event_id` 
    AND `eo2`.`market_id` = '.$win_market->id.'  
    AND `eo2`.`market_value_id` = '.$draw_market_value->id.'  
    AND `eo2`.`bookmaker_id` IN('.implode(',', $enabled_bookmaker_ids).') 
    AND `eo2`.`value` = `eo2`.`best_odd` 
LEFT JOIN `event_odds` AS `eo3` 
    ON `events`.`id` = `eo3`.`event_id` 
    AND `eo3`.`market_id` = '.$win_market->id.'  
    AND `eo3`.`market_value_id` = '.$away_market_value->id.'  
    AND `eo3`.`bookmaker_id` IN('.implode(',', $enabled_bookmaker_ids).') 
    AND `eo3`.`value` = `eo3`.`best_odd` 
LEFT JOIN `event_odds` AS `eo4` 
    ON `events`.`id` = `eo4`.`event_id` 
    AND `eo4`.`market_id` = '.$ou_market->id.'  
    AND `eo4`.`market_value_id` = '.$over_market_value->id.'  
    AND `eo4`.`bookmaker_id` IN('.implode(',', $enabled_bookmaker_ids).') 
    AND `eo4`.`value` = `eo4`.`best_odd` 
LEFT JOIN `event_odds` AS `eo5` 
    ON `events`.`id` = `eo5`.`event_id` 
    AND `eo5`.`market_id` = '.$ou_market->id.'  
    AND `eo5`.`market_value_id` = '.$under_market_value->id.'  
    AND `eo5`.`bookmaker_id` IN('.implode(',', $enabled_bookmaker_ids).')
    AND `eo5`.`value` = `eo5`.`best_odd` 
WHERE `events`.`sport_id` IN('.implode(',', $enabled_sports_ids).') 
AND `events`.`event_datetime` > '.time().' 
GROUP BY `events`.`id` 
ORDER BY 
    `leagues`.`major` DESC, 
    `leagues`.`name` ASC, 
    `events`.`event_datetime` ASC 
LIMIT 50 OFFSET 0';

如果我使用eloquent来构建查询而不执行它需要1.899秒,而如果我使用字符串方法需要0.006秒。

我更愿意使用雄辩,但我无法像这样表现出色,我能做些什么来加速用雄辩的方式构建查询?

0 个答案:

没有答案