I have a MySQL query with a particular structure that I want to rewrite so that it runs faster. It currently runs very slow taking about 255 seconds to execute. If I remove the join it runs in < 10 seconds. Its purpose is to get records from table A, 100 rows at a time, for as long as a user wants to see more rows.
I suspect that the query is taking a long time because it's doing the join on more than just the first 100 rows it finds. Is this true, and if so, is there a way to rewrite the query to do the joining after it gets the rows from the main table?
The data comes from a 'main' table A which has a datetime field (START_TIME) and several foreign keys to tables with string values (tables, B,C,D).
Table A has 2.5 million rows. Table B has 600K rows. Table A has an index on START_TIME. Table B has an index on its ID value.
Here's a basic form of the query. I do not want to put an upper limit on START_TIME because I ALWAYS want to get 100 records back from the query. I use a response which has less than 100 records to indicate that there`s no more records in the database.
SELECT
A.START_TIME, A.F1, A.F2, B.STRING
FROM
A
INNER JOIN B ON A.B_ID = B.ID
WHERE
A.START_TIME >= '2015-03-22 05:23:44'
LIMIT 0, 100;
Here`s the EXPLAIN. Sorry for the format:
# id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra
1, SIMPLE, B, index, PRIMARY, FSN, 95, , 1, Using index; Using temporary; Using filesort
1, SIMPLE, A, ref, A_ix_B_ID,A_ix_C, A_ix_B_ID, 4, ag100_a$$burnaby.B.ID, 2, Using where
You have to provide explain plan so we can help you better.
https://dev.mysql.com/doc/refman/5.5/en/execution-plan-information.html
But for your description you still need index.
TableA beside START_TIME
need index for each join field B_id, C_id and D_id
and maybe using a composite index for all 4 variable would be better
CREATE INDEX A_Bid_idx ON A (B_id);
CREATE INDEX A_Cid_idx ON A (C_id);
CREATE INDEX A_Did_idx ON A (D_id);
OR
CREATE INDEX A_Full_idx ON A (B_id,C_id, D_id, START_TIME);
Table C and D also need index for C.ID and D.ID
. And would be even better if they use a composite index
(C.ID, C.STRING) and
(D.ID, D.STRING)
CREATE INDEX C_id_idx ON C (ID);
CREATE INDEX D_id_idx ON D (ID);
OR
CREATE INDEX C_id_string_idx ON C (ID, STRING);
CREATE INDEX D_id_string_idx ON C (ID, STRING);
That way db doesnt have to make a lookup to find the string value asociated to the ID
SELECT A.START_TIME, A.F1, A.F2,
( SELECT STRING
FROM B
WHERE A.B_ID = B.ID
) AS String
FROM A
WHERE A.START_TIME >= '2015-03-22 05:23:44'
ORDER BY START_TIME
LIMIT 0, 100;
will probably run faster. It is 'forced' to use INDEX(START_TIME)
from A
.
Please provide SHOW CREATE TABLE
for both tables; I want to check the datatypes, etc.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.