i developed a website where two team can face each other. The first team create a match search m
for a certain value
(stack), with status
= search. The first team has a elo
(level) attribute.
When the second team (which have a elo of 150) will search a match, we execute the following query:
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
The problem is that this query is very long even if we only have 15000 user_match (there are only 40 rows that answer the requirements with value = 0.5, status = search) and 15000 teams (there are 5570 teams that answer the requirements with elo and id)
I tried to EXPLAIN
the request, and here is the result:
If there is no opponent when a user searches a match, the request can take like 3 minutes, and this time will be reduce when the same request is executed many times (cache ?), and it's faster if there is an opponent.
The last thing I could precise is that user_match table contains a detail
attribute that contains an heavy json_array ONLY IF the match status = ended
Do you know if it's the regular execution time ? What could I do to improve that ?
Thanks !
First, don't repeat the condition on t.id = m.team_one_id
. So, this is your query:
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;
Second, the query looks suspicious because you have LIMIT
with no ORDER BY
. Typically, you want an ORDER BY
so the row you return is guaranteed to be the same on each execution.
Indexes are how you speed queries. I would start with the following indexes:
user_match(status, value, team_one_id)
team(id, elo)
The index on user_match
is the best for that table based on the where
clause. Note: If value
is a number, then do not use single quotes around the 0.5
, that can confuse the optimizer.
The second index on team
is not necessary if id
is declared as the primary key.