Here are the sql commands I’ve done, and I don’t understand why there’s so few difference between without the key (~1.45 s), and with the key (~1.15 s):
mysql> show create table devis;
| devis | CREATE TABLE `devis` (
`id` bigint(20) unsigned NOT NULL auto_increment,
...blabla...
`date_v_creation` datetime default NULL,
`date_v_fin` datetime default NULL,
...blabla...
`etat` tinyint(4) default NULL,
`etat_date` datetime default NULL,
PRIMARY KEY (`id`),
KEY `date_v_creation` (`date_v_creation`),
KEY `date_v_fin` (`date_v_fin`),
...blabla...
) ENGINE=InnoDB AUTO_INCREMENT=3714317 DEFAULT CHARSET=utf8 |
mysql> select date_v_creation from devis
where etat=3
and date_v_fin is null
and TO_DAYS(NOW()) - TO_DAYS(date_v_creation) > 54;
+---------------------+
| date_v_creation |
+---------------------+
| 2011-10-30 21:44:54 |
| ...blabla... |
| 2011-10-30 21:48:05 |
+---------------------+
216 rows in set (1.45 sec)
mysql> alter table devis add key( date_v_fin, etat);
mysql> select date_v_creation from devis
where etat=3
and date_v_fin is null
and TO_DAYS(NOW()) - TO_DAYS(date_v_creation) > 54;
+---------------------+
| date_v_creation |
+---------------------+
| 2011-10-30 21:44:54 |
| ...blabla... |
| 2011-10-30 21:48:05 |
+---------------------+
216 rows in set (1.13 sec)
If I do it a lot of times, it’s always between (1.05 sec) and (1.15 sec).
There have been a lot of times where I’ve added keys to have a shorter response time, and when it didn’t work, the time didn’t change, and when it worked, the time change to a factor of 10 to the least.
Am I doing something wrong, missing something or is this normal t gain so few?
Thanks a lot!
Update
Here’s the query that solved my problem but I still don’t get why it solved it.
select date_v_creation
from devis
where etat=3
and date_v_creation < NOW() - INTERVAL 54 DAY
and date_v_fin is null;
Here’s the explain of my “bad” query:
mysql> EXPLAIN select date_v_creation from devis where etat=3 and date_v_fin is null and TO_DAYS(NOW()) - TO_DAYS(date_v_creation) > 54;
+----+-------------+-------+------+-------------------------+------------+---------+-------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+-------------------------+------------+---------+-------+-------+-------------+
| 1 | SIMPLE | devis | ref | date_v_fin,date_v_fin_2 | date_v_fin | 9 | const | 15913 | Using where |
+----+-------------+-------+------+-------------------------+------------+---------+-------+-------+-------------+
1 row in set (0.34 sec)
Here’s the explain of the “good”, optimized query:
mysql> explain select date_v_creation from devis where etat=3 and date_v_creation < NOW() - INTERVAL 54 DAY and date_v_fin is null;
+----+-------------+-------+-------+-----------------------------------------+-----------------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+-----------------------------------------+-----------------+---------+------+------+-------------+
| 1 | SIMPLE | devis | range | date_v_fin,date_v_creation,date_v_fin_2 | date_v_creation | 9 | NULL | 1458 | Using where |
+----+-------------+-------+-------+-----------------------------------------+-----------------+---------+------+------+-------------+
1 row in set (0.00 sec)
You have basically two problems:
the index on
date_v_creationcurrently can not be used, because the comparison is on a function of the field value instead of the value itself. That’s why the key ondate_v_creationdid not help. SO you should rewrite the query as follows: