I have a query:
SELECT abt.duration, a.id, a.a_id, a.a_tag
FROM active_begin_times AS abt INNER JOIN sources AS a ON a.id = abt.a_source
AND a.u IN (29, 28, 27, 26, 25, 24)
WHERE (abt.duration > 86400000)
and (abt.begin_timestamp<=1465185600000 and 1465617600000<=abt.end_timestamp
OR 1465185600000<=abt.begin_timestamp and abt.begin_timestamp<=1465617600000
OR 1465185600000<=abt.end_timestamp and abt.end_timestamp<=1465617600000)
order by abt.begin_timestamp asc LIMIT 0, 10
The database has about 5 Million entries. This query takes about 30 seconds to run. But if I change by what I order the table to duration, it is calculated within fraction of seconds, like in query below:
SELECT abt.duration, a.id, a.a_id, a.a_tag
FROM active_begin_times AS abt INNER JOIN sources AS a ON a.id = abt.a_source
AND a.u IN (29, 28, 27, 26, 25, 24)
WHERE (abt.duration > 86400000)
and (abt.begin_timestamp<=1465185600000 and 1465617600000<=abt.end_timestamp
OR 1465185600000<=abt.begin_timestamp and abt.begin_timestamp<=1465617600000
OR 1465185600000<=abt.end_timestamp and abt.end_timestamp<=1465617600000)
order by abt.duration asc LIMIT 0, 10
I have indexes on both duration and on begin_timestamp. And when I changed the order by to abt.id, it again took a lot of time to calculate, which also has indexes.
Also, what I noticed is for this particular set of conditions, the query returns 2 rows. But if I change the variables and I get this query to return 20 to 30 odd rows, then the calculations are instantaneous.
Could someone please explain, the above 2 cases? I tried looking in SO but could not either understand the behaviour or was not satisfied with the explanation.
The EXPLAIN
for the first query returns:
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
|----|-------------|-------|--------|----------------------------------------------------------|-----------------|---------|-----------------------|------|-------------|
| 1 | SIMPLE | abet | index | FK2681F9347A6A34B,begin_timestamp,end_timestamp,duration | begin_timestamp | 9 | \N | 6094 | Using where |
| 1 | SIMPLE | a | eq_ref | PRIMARY,FK722DBCA9F603AF | PRIMARY | 4 | db.abt.alarm_source | 1 | Using where |
And from the second query I get:
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
|----|-------------|-------|--------|----------------------------------------------------------|----------|---------|-----------------------|------|------------------------------------|
| 1 | SIMPLE | abet | range | FK2681F9347A6A34B,begin_timestamp,end_timestamp,duration | duration | 9 | \N | 8597 | Using index condition; Using where |
| 1 | SIMPLE | a | eq_ref | PRIMARY,FK722DBCA9F603AF | PRIMARY | 4 | db.abt.alarm_source | 1 | Using where |
I visible difference I can see is in the Extras
columns where in the 2 query is says Using index condition;
, bit I am not sure what to make of it.
The output of SHOW CREATE TABLE active_begin_time:
CREATE TABLE active_begin_times (
id int(11) NOT NULL AUTO_INCREMENT,
begin_timezone_offset int(11) DEFAULT NULL,
begin_timezone_suffix varchar(100) DEFAULT NULL,
begin_timestamp bigint(20) DEFAULT NULL,
begin_timestamp_date varchar(100) DEFAULT NULL,
duration bigint(20) DEFAULT NULL,
end_timezone_offset int(11) DEFAULT NULL,
end_timezone_suffix varchar(100) DEFAULT NULL,
end_timestamp bigint(20) DEFAULT NULL,
end_timestamp_date varchar(100) DEFAULT NULL,
incomplete int(11) DEFAULT NULL,
a_source int(11) DEFAULT NULL,
PRIMARY KEY (id),
KEY FK2681F9347A6A34B (alarm_source),
KEY begin_timestamp (begin_timestamp),
KEY end_timestamp (end_timestamp),
KEY begin_timezone_offset (begin_timezone_offset),
KEY end_timezone_offset (end_timezone_offset),
KEY duration (duration),
KEY begin_timestamp_date (begin_timestamp_date),
KEY end_timestamp_date (end_timestamp_date)
) ENGINE=MyISAM AUTO_INCREMENT=6164640 DEFAULT CHARSET=latin1