If I create the following two indicies
ALTER TABLE requests ADD INDEX daily_ips(exec_date, ip_address);
ALTER TABLE requests ADD INDEX is_cached(exec_date, cached);
The output of show index from requests
is the following
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
requests 1 daily_ips 1 exec_date A 413 NULL NULL YES BTREE
requests 1 daily_ips 2 ip_address A 218334 NULL NULL YES BTREE
requests 1 is_cached 1 exec_date A 165 NULL NULL YES BTREE
requests 1 is_cached 2 cached A 165 NULL NULL YES BTREE
I have the following query
EXPLAIN SELECT exec_date,
100 * SUM(CASE WHEN cached = 'no' THEN 1 ELSE 0 END) / SUM(1) cached_no,
100 * SUM(CASE WHEN cached != 'no' THEN 1 ELSE 0 END) / SUM(1) cached_yes
FROM requests
GROUP BY exec_date;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE requests index NULL daily_ips 263 NULL 436695
However I would like to force the query optimizer to use the is_cached
index instead of daily_ips
index.
If I remove the daily_ips
index and add it again
ALTER TABLE requests DROP INDEX daily_ips;
ALTER TABLE requests ADD INDEX daily_ips(exec_date, ip_address);
Then run the same EXPLAIN
statement, the query optimizer chooses the is_cached
index.
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE requests index NULL is_cached 6 NULL 440493 Using index
Is it expected behavior for the query optimizer to choose an index based on the order it was added?
How do I tell the query optimizer which index to use?
You can specify that which index sholud be used by query to run.
Try this:
EXPLAIN SELECT exec_date,
100 * SUM(CASE WHEN cached = 'no' THEN 1 ELSE 0 END) / SUM(1) cached_no,
100 * SUM(CASE WHEN cached != 'no' THEN 1 ELSE 0 END) / SUM(1) cached_yes
FROM requests USE INDEX(is_cached)
GROUP BY exec_date;
Differnce between USE INDEX
and FORCE INDEX
:
By specifying USE INDEX (index_list), you can tell MySQL to use only one of the named indexes to find rows in the table. The alternative syntax IGNORE INDEX (index_list) can be used to tell MySQL to not use some particular index or indexes. These hints are useful if EXPLAIN shows that MySQL is using the wrong index from the list of possible indexes.
You can also use FORCE INDEX, which acts like USE INDEX (index_list) but with the addition that a table scan is assumed to be very expensive. In other words, a table scan is used only if there is no way to use one of the given indexes to find rows in the table.
UPDATE
Try this Query:
SELECT exec_date,
100 * SUM(IF(cached = 0, 1, 0)) / SUM(1) cached_no,
100 * SUM(IF(cached = 1, 1, 0)) / SUM(1) cached_yes
FROM (SELECT exec_date, IF(cached = 'no', 0, 1) cached
FROM requests GROUP BY exec_date) AS A
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With