如何优化MySQL多表选择查询?

关志伟

我的MySQL查询代码如下所示,并且该表中大约有数千条记录,到现在SQL在下面执行约5分钟或更长时间。我正在寻找对其进行优化的方法,以减少执行时间。谢谢!

SELECT `m`.`id`,
   `m`.`id`,
   `tr`.`name`,
   `m`.`m_date`,
   `t1`.`t_name` AS home,
   `t2`.`t_name` AS away,
   `m`.`score1`,
   `m`.`score2`,
   `cw1`.`tid` AS tid1,
   `cw2`.`tid` AS tid2,
   `o1`.`odds` AS odds1,
   `o2`.`odds` AS odds2,
   `m`.`m_time`
FROM `jos_bl_match` AS `m`
LEFT JOIN `jos_bl_matchday` AS `md` ON (`md`.`id` = `m`.`m_id`)
LEFT JOIN `jos_bl_seasons` AS `s` ON (`s`.`s_id` = `md`.`s_id`)
LEFT JOIN `jos_bl_tournament` AS `tr` ON (`tr`.`id` = `s`.`t_id`)
LEFT JOIN `jos_bl_teams` AS `t1` ON (`m`.`team1_id` = `t1`.`id`)
LEFT JOIN `jos_bl_teams` AS `t2` ON (`m`.`team2_id` = `t2`.`id`)
LEFT JOIN `jos_vuvuzelaodds_odds` AS `o1` ON (`o1`.`m_id` = `m`.`id`)
AND `o1`.`market_id` = 1
AND `o1`.`bookmaker_id` = 1
LEFT JOIN `jos_vuvuzelaodds_odds` AS `o2` ON (`o2`.`m_id` = `m`.`id`)
AND `o2`.`market_id` = 1
AND `o2`.`bookmaker_id` = 2
LEFT JOIN `jos_cwtags_tags` AS `cw1` ON (`cw1`.`item_id` = `o1`.`m_id`)
LEFT JOIN `jos_cwtags_tags` AS `cw2` ON (`cw2`.`item_id` = `o2`.`m_id`)
WHERE `m`.`published` = 1
AND `s`.`published` = '1'
AND `tr`.`published` = '1'
AND `s`.`s_id` = 869
AND `m`.`m_played` = '1'
AND `m`.`m_date` > 2013-01-01
AND `o1`.`odds` != ''
AND `o2`.`odds` != ''
AND `cw1`.`cat_id` = 19
AND `cw2`.`cat_id` = 21
ORDER BY `m`.`m_date`,
     `md`.`id`,
     `s`.`s_id`,
     `tr`.`id` DESC LIMIT 0, 15
克里斯·亚当斯(Chris Adams)

如果没有访问数据库的权限,这很难说。这似乎是很多数据,只能提取15条记录。您确定需要以这种方式提取数据吗?

最好的路线:

  • 如下优化数据库。
  • 为具有所需字段的所有游戏制作一个平面数据库视图。静态表会更快,但是您需要使用触发器来设置更新,这超出了此答案的范围,但是过程类似
  • 针对视图编写查询。

您没有从选择的季节表中选择任何字段。我使用了jos_bl_matchday表中的字段。

这应该可以帮助您入门。您还可以在选择语句中使用条件

(IF value = 1, table.field, null) as yadda 

而不是一遍又一遍地联接一张桌子,但是您必须进行试验。

CREATE VIEW allTheGames AS SELECT
`m`.`id` as id,
`md`.`s_id` as seasonId, 
  `tr`.`name` as name,
 `m`.`m_date` as m_date,
 `t1`.`t_name` AS home,
 `t2`.`t_name` AS away,
`m`.`score1` as score1,
 `m`.`score2` as score2,
 `cw1`.`tid` AS tid1,
 `cw2`.`tid` AS tid2,
 `o1`.`odds` AS odds1,
 `o2`.`odds` AS odds2,
 `m`.`m_time` as m_time 
          FROM `jos_bl_match` AS `m` 
          LEFT JOIN `jos_bl_matchday` AS `md` ON (`md`.`id` = `m`.`m_id`) 
          LEFT JOIN `jos_bl_tournament` AS `tr` ON (`tr`.`id` = `s`.`t_id`) 
          LEFT JOIN `jos_bl_teams` AS `t1` ON (`m`.`team1_id` = `t1`.`id`) 
          LEFT JOIN `jos_bl_teams` AS `t2` ON (`m`.`team2_id` = `t2`.`id`) 
          LEFT JOIN `jos_vuvuzelaodds_odds` AS `o1` ON (`o1`.`m_id` = `m`.`id`) AND `o1`.`market_id` = 1 AND `o1`.`bookmaker_id` = 1 
          LEFT JOIN `jos_vuvuzelaodds_odds` AS `o2` ON (`o2`.`m_id` = `m`.`id`) AND `o2`.`market_id` = 1 AND `o2`.`bookmaker_id` = 2 
          LEFT JOIN `jos_cwtags_tags` AS `cw1` ON (`cw1`.`item_id` = `o1`.`m_id`) 
          LEFT JOIN `jos_cwtags_tags` AS `cw2` ON (`cw2`.`item_id` = `o2`.`m_id`) 
          WHERE `m`.`published` = 1 AND `s`.`published` = '1' AND `tr`.`published` = '1' 
          AND `m`.`m_played` = '1' 
          AND `o1`.`odds1` != '' AND `o2`.`odds2` != ''

然后使用以下查询:

select * from allTheGames 
  WHERE season_id = 869 AND m_date > 2013-01-01  AND tid1 = 19 AND tid2 = 21 

优化步骤:

准确找出您要从该查询中获取哪些数据,以及原因:这是自定义报告吗?一个网页?您是否需要一次拥有所有这些数据,还是让用户进行深入分析更有意义?查询多久运行一次?一分钟一次 一天一次?每个表中有几条记录?您的视图应反映此“游戏对象”

您的数据库:

  • 针对此查询http://dev.mysql.com/doc/refman/5.7/en/explain.html运行“解释”
  • 它将显示数据库正在执行的所有工作,查询执行计划以及正在查找的记录数量。这通常会很快发生:它实际上并不执行查询。
  • 看看是否可以将数据库放在SSD驱动器甚至RAM上

您的表格结构:

  • 确保在要搜索的所有字段上都有索引。有很多方法可以对此进行优化。
  • 使用“解释”以确保MySQL能够使用索引。
  • 如果jos_vuvuzelaodds_odds表中确实只有2个市场,请考虑进行2个字段。

祝你好运!

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章