Query optimization in MySQL
-
15-06-2021 - |
Frage
At first, i have to say that this topic is very common topic. I have studied all related topics but i can not find out the answer. I have three tables. Messages table has 300.000, tags table has 1 million and message_tag table has about 10 million rows. message_tag.message_id and message_tag.tag_id columns have indexes. My purpose is select messages which linked a spesified tag. However query times are too long. There is not any query time shorter than 20 seconds. On the other hand sometimes query does not give even a result due to long query times. Table structures and my query are below. How can i handle this problem? I am open all suggestions. Even i can recreate tables with a new schema. Database is MySql, Storage motor is MyIsam. .
table name: messages
columns :
id (int)
message (vharchar)
message_poster (vharchar)
table name: tags
id (int)
tag (vharchar)
table name : message_tag
columns :
message_id (int)
tag_id (int)
My query:
SELECT messages.message_poster,
messages.message
FROM tags, messages, message_tag
WHERE message_tag.tag_id=191
AND messages.id= message_tag.message_id
Lösung
And here is an example of why I don't like using ,
notation.
You don't relate message_tag
to tags
. Instead, you join EVERY message tag to every other row.
This is what you have...
SELECT
messages.message_poster,
messages.message
FROM
messages
INNER JOIN
message_tag
ON messages.id= message_tag.message_id
CROSS JOIN
tags
WHERE
message_tag.tag_id=191
This is what you should have...
SELECT
messages.message_poster,
messages.message
FROM
messages
INNER JOIN
message_tag
ON messages.id = message_tag.message_id
INNER JOIN
tags
ON tags.id = message_tag.tag_id
WHERE
message_tag.tag_id = 191
(Or, just don't JOIN on tags
at all, you're not using it in this case. Though I appreciate that this may be a simplified version of the actual query.)
It's much harder to mess that up with ANSI-92
notation.
Andere Tipps
Create a two-dimensional index on message_tag (over both fields), and rewrite the WHERE to
WHERE
message_tag.tag_id=191 AND
message_tag.message_id = messages.id
I think you're missing a join condition between 2 tables, maybe tags
and message_tag
?