【问题标题】:How to optimize MySQL multiple tables select queries?如何优化 MySQL 多表选择查询?
【发布时间】:2017-02-08 12:25:18
【问题描述】:

我的 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

【问题讨论】:

    标签: mysql sql database select optimization


    【解决方案1】:

    如果无法访问数据库,这有点难以判断。这似乎是很多数据只能拉 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 个字段。

    祝你好运!

    【讨论】:

      【解决方案2】:

      “标准化,但不要过度标准化。”

      您可能缺少一些复合索引...

      jos_bl_match: INDEX(m_played, published, m_date)
      

      列必须按该顺序排列。这将更快地开始过滤。

      以下应该加速他们的 JOIN:

      jos_vuvuzelaodds_odds: INDEX(market_id, bookmaker_id, m_id)
      jos_cwtags_tags: INDEX(cat_id, item_id)
      

      似乎最后两个索引可能(应该)是PRIMARY KEY。是吗?

      LEFT JOINs 中的一些(可能是全部)也可能是INNER JOINs;你考虑过吗?

      请提供EXPLAIN SELECT

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-10
        • 2019-04-22
        相关资源
        最近更新 更多