2016-09-30 63 views
-1

我的MySQL查詢代碼如下所示,並且表中有大約幾千條記錄,到現在爲止,SQL執行大約5分鐘甚至更多。我正在尋找優化方法,以便執行時間更短。謝謝!如何優化MySQL多個表選擇查詢?

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 

回答

-1

沒有訪問數據庫,有點難以分辨。這似乎是很多數據只能拉出15條記錄。你確定你需要這樣拉取數據嗎?

也許是最好的途徑:

  • 優化數據庫如下。
  • 製作具有所需字段的所有遊戲的平面數據庫視圖。靜態表會快得多,但您需要使用觸發器設置更新,這超出了本答案的範圍,但過程與此類似。
  • 針對 視圖編寫查詢。

您並未從選擇中的季節表中選擇任何字段。我使用jos_bl_matchday表中的字段。

這應該讓你開始。您也可以使用條件在SELECT語句

(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

你的表結構:

  • 請確保您有所有您正在搜索的領域的指標。有很多方法可以優化這個。
  • 使用「explain」來確保MySQL能夠使用索引。
  • 如果jos_vuvuzelaodds_odds表中真的只有2個市場考慮製作2個字段。

祝你好運!

1

「標準化,但不要過度標準化。」

你可能會丟失一些複合索引...

jos_bl_match: INDEX(m_played, published, m_date) 

列需要在這個順序。這將更快地開始過濾。

下應加快其聯接:

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