簡體   English   中英

MySQL很長查詢,內連接

[英]MySQL very long query, inner join

我開發了一個網站,兩個團隊可以互相面對面。 第一個團隊為某個value (堆棧)創建匹配搜索mstatus =搜索。 第一個團隊具有elo (級別)屬性。 當第二個團隊(elo為150)將搜索匹配時,我們執行以下查詢:

SELECT m.id, m.value, m.teamOneScore, m.teamTwoScore, m.date, m.status, m.detail, m.team_one_id, m.team_two_id 
FROM user_match m
INNER JOIN team t ON m.team_one_id = t.id 
WHERE t.id = m.team_one_id 
    AND t.id <> 3        // You don't want to play against your own team
    AND t.elo <= 200     // 50 of elo range for example
    AND t.elo >= 100 
    AND m.value = '0.5'  
    AND m.status = 'search'
LIMIT 1

問題是這個查詢很長,即使我們只有15000 user_match(只有40行符合要求,值= 0.5,狀態=搜索)和15000個團隊(有5570個團隊用elo和id)我試圖EXPLAIN請求,結果如下:

在此輸入圖像描述

如果用戶搜索匹配時沒有對手,則請求可能需要3分鍾,並且當多次執行相同請求時,此時間將減少(緩存?),如果有對手則更快。

我可以精確的最后一點是user_match表包含一個detail屬性,只有匹配狀態=結束時才包含重json_array

你知道這是正常的執行時間嗎? 我該怎么做才能改善這一點?

謝謝 !

直截了當,您需要使用where子句索引列。

據解釋,似乎mysql計划只使用pk作為索引。 並且你的pk在哪里使用列來排除只有單行。 因此,mysql將掃描除單行之外的所有表。

在這種情況下,您必須索引elo列以使查詢計划掃描最少的行。

ALTER TABLE team ADD INDEX search(id, elo);

然后查看查詢時間。

+編輯它似乎上面的解決方案並沒有多少提高查詢時間。

這是另一點。 您需要在join子句中首先放置較小的范圍表。 使用上面的索引,團隊表將更小。 因此查詢將如下所示。

SELECT m.id, m.value, m.teamOneScore, m.teamTwoScore, m.date, 
       m.status, m.detail, m.team_one_id, m.team_two_id
FROM team t
INNER JOIN user_match m ON m.team_one_id = t.id 
WHERE 
t.elo <= 200     // 50 of elo range for example
AND t.elo >= 100
AND t.id <> 3        // You don't want to play against your own team
AND m.value = '0.5'  
AND m.status = 'search'
LIMIT 1

讓我看看這是否適合你

首先,不要在t.id = m.team_one_id上重復這個條件。 所以,這是你的查詢:

SELECT m.id, m.value, m.teamOneScore, m.teamTwoScore, m.date, m.status, m.detail, m.team_one_id, m.team_two_id 
FROM user_match m INNER JOIN
     team t
     ON m.team_one_id = t.id 
WHERE t.id <> 3 AND     // You don't want to play against your own team
      t.elo <= 200 AND    // 50 of elo range for example
      t.elo >= 100 AND
      m.value = '0.5' AND
      m.status = 'search'
LIMIT 1;

其次,查詢看起來很可疑,因為你有LIMIT沒有ORDER BY 通常,您需要ORDER BY因此您返回的行在每次執行時都保證相同。

索引是您加快查詢速度的方式。 我將從以下索引開始:

  • user_match(status, value, team_one_id)
  • team(id, elo)

user_match上的索引對於基於where子句的表是最佳的。 注意:如果value是一個數字,那么不要在0.5周圍使用單引號,這可能會使優化器混淆。

如果將id聲明為主鍵,則不需要team的第二個索引。

我認為您可以嘗試通過為主要查詢的列提供索引,就像列currently present in where condition. ..

如果它們沒有編入索引,那么你可以嘗試“更改查詢以向列添加索引”,然后查看響應時間。

當你在join子句中使用它時,為什么在where子句中需要t.id = m.team_one_id(INNER JOIN team t ON m.team_one_id = t.id)? 我相信這是多余的。

我認為你應該在ON子句中移動團隊過濾器並得到這樣的東西

SELECT m.id, m.value, m.teamOneScore, m.teamTwoScore, m.date, m.status, m.detail, m.team_one_id, m.team_two_id 
FROM user_match m
INNER JOIN team t ON m.team_one_id = t.id and t.id <> 3 and t.elo <= 200 and t.elo >= 100
WHERE m.value = '0.5'  
    AND m.status = 'search'
LIMIT 1

然后在user_match表的value和status列上添加復合索引。

ALTER TABLE user_match ADD INDEX usermatchteam_idx(value, status);

和上面評論中提到的團隊表索引

ALTER TABLE team ADD INDEX elosearch_idx(id, elo);

請嘗試這種方法。 如果這沒有幫助,請為team和user_match表提供創建表,以便我們進一步調查。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM