Forum Moderators: open

Message Too Old, No Replies

MySQL, why is this JOIN query slow?

         

csdude55

8:16 pm on Dec 29, 2020 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I have a table that has 2.1G in data, 500.8M in index (3 indexes), and there are 10.2 million rows.

I'm joining with a much smaller table that's 9.7M in data, 17.9M in index (3 indexes), and 362,000 rows.

Here's the query:

SELECT table_A.id, username, folder, status, postdate, sender, subject, message, table_B.image
FROM table_A
LEFT JOIN table_B
ON table_B.id = table_A.id
WHERE username='example' AND folder='inbox'
# this is actually all of the possible values for status, so I tested with and without this line
AND (status = "New" OR status = "" OR status IS NULL)

AND COALESCE(table_B.sorter,0) = 0
ORDER BY POSTDATE DESC
LIMIT 21

# offset is there because I paginate
OFFSET 0

# I also tried this, but it was no different:
SELECT table_A.id, username, folder, status, postdate, sender, subject, message, table_B.image
FROM table_A
LEFT JOIN table_B
ON table_B.id = table_A.id
AND COALESCE(table_B.sorter,0) = 0
WHERE username='example' AND folder='inbox'
AND (status = "New" OR status = "" OR status IS NULL)
ORDER BY POSTDATE DESC
LIMIT 21
OFFSET 0


The problem I'm having is when there are a lot of rows that match the WHERE, the query time is much slower! For example, I have one where there are 14,645 matches, and the query takes 4.960s to complete. Another has 3,269 matches, and the query took 3.0691s.

When I use Explain:

table: table_A
type: range
possible_keys: New Messages

# this index is on username, folder, and status
key: New Messages

key_len: 106
key_ref: NULL
rows: 8944
Extra: Using index condition; Using where; Using filesort

table: table_B
type: ref
possible_keys: id_2,ID,View

# this index is on id, sorter, and image; id_2 is on id and sorter, but I used "USE INDEX (id_2)" and it had no impact
key: View

key_len: 4
ref: goncco_forum.private_messages.id
rows: 1
Extra: Using where; Using index


But when I do the same query without joining with table_B, it finishes in 0.0655s. So the delay is definitely coming from the JOIN, but I can't see why?

Kendo

9:15 pm on Dec 29, 2020 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I almost never used joined tables where they can be spidered.

csdude55

2:05 am on Dec 30, 2020 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



What do you mean by "spidered"?

robzilla

9:16 am on Dec 30, 2020 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



SET profiling=1;
[execute your query]
SHOW PROFILE;
SET profiling=0;

Kendo

5:20 am on Dec 31, 2020 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



What do you mean by "spidered"?

Indexed by bots, search engines hackware.

phranque

5:30 am on Dec 31, 2020 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



I almost never used joined tables where they can be spidered.

Indexed by bots, search engines hackware.

are you talking about SQL injection?

csdude55

5:36 am on Dec 31, 2020 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Well... query time was 5.6634s, but I don't see a bottleneck anywhere:

Status  Duration
Starting 0.000016
Waiting for query cache lock 0.000009
Init 0.000008
Checking query cache for query 0.000022
Checking permissions 0.000008
Opening tables 0.000007
After opening tables 0.000009
Init 0.000014
Optimizing 0.000012
Executing 0.000012
End of update loop 0.000008
Query end 0.000007
Commit 0.000007
Closing tables 0.000007
Starting cleanup 0.000007
Freeing items 0.000008
Updating status 0.000018
Reset for next command 0.000008

robzilla

8:14 am on Dec 31, 2020 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



That appears to be the profile of a different query. Perhaps profiling was enabled for all sessions. Run SHOW PROFILES; to view all stored profiles, then find the number for the query above (e.g. 4) and run SHOW PROFILE FOR QUERY 4;

Kendo

7:59 am on Jan 5, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



are you talking about SQL injection?

No. It's about the greatly increased load on the server resources.

LifeinAsia

10:21 pm on Jan 6, 2021 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



Did you try adding an index to table_A.id?

csdude55

10:31 pm on Jan 6, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



There actually is an index on it, as a PRIMARY.

Oddly, though, I haven't had any slow queries show up in my log since January 1! There's no explanation for it, though, as I haven't changed anything here. So this problem is on hold for now until I see it in the log again. Good gremlins, I guess?