Reputation: 833
I performed a search on MySQL on the following table that has following columns and indexes:
The query was the following, please notice the number of days as 6:
SELECT * FROM data WHERE TEMP<"3000" AND TEMP>"2600" AND Date_Time >"2016-05-05 %" and Date_Time <"2016-05-11 %";
This query returns the results in 0.59s
If I change the number of days to more than that like in this query then I will get the result in a lot more time 2.15s
SELECT * FROM data WHERE TEMP<"3000" AND TEMP>"2600" AND Date_Time >"2016-05-04 %" and Date_Time <"2016-05-11 %";
How do I fix this issue? I find it absurd that only another day affects the speed that much! I am aiming to search in a wider range of time, so I somewhat need to know the reason behind this.
Upvotes: 3
Views: 1344
Reputation: 36
Fact 1: MySQL cannot use more than 1 index in your case
As explained in this blog post https://www.percona.com/blog/2009/09/12/3-ways-mysql-uses-indexes/
if you have index on (A,B) This index can be used to lookup rows for WHERE clauses like A=5 ; A BETWEEN 5 AND 10 ; A=5 AND B BETWEEN 5 AND 10 it however will NOT be able to help lookup rows for B BETWEEN 5 AND 10 predicate because it is not index prefix.
So, in your case that you have the columns TEMP and Date_Time and you search by range, the range index will be used for either TEMP or Date_Time and the second part of the query will be executed using where. This is structural limitation of BTREE indexes.
Fact 2: The index is not covering your query, which means query cannot be executed using only data from the index without reading the row itself
A full table scan is performed using reads from the index to look up data rows > in index order. Uses index does not appear in the Extra column. http://dev.mysql.com/doc/refman/5.7/en/explain-output.html#jointype_range
So what happens in your first query:
1. MySQL will lookup for Date_Time in Date_Time index and choose the index_rows that fit 'Date_Time >"2016-05-05 %" and Date_Time <"2016-05-11 %"'
2. In the index the TEMP info is not available, so MySQL needs to collect all the index_rows from the data table.
3. MySQL will evaluate the condition 'TEMP<"3000" AND TEMP>"2600"' on each one of these rows.
What happens in the second query?
MySQL decides not to use any of the available indexes (possible_keys) and performs a full table scan to return the values. This means that each row of the table will be scanned to check if matches the conditions TEMP<"3000" AND TEMP>"2600" AND Date_Time >"2016-05-04 %" and Date_Time <"2016-05-11 %".
This probably happens because there is no value with prefix "2016-05-11" or "2016-05-04".
Upvotes: 1