以下是我已经完成的sql命令,我不明白为什么没有密钥(~1.45 s)和密钥(~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)
如果我这么做很多次,它总是介于(1.05秒)和(1.15秒)之间。
很多时候,我添加了密钥以缩短响应时间,当它不起作用时,时间没有改变,当它工作时,时间变为从最低的10倍到。
我做错了什么,错过了什么,或者这种正常收益是如此之少?
非常感谢!
这是解决我的问题的查询,但我仍然不知道为什么它解决了它。
select date_v_creation
from devis
where etat=3
and date_v_creation < NOW() - INTERVAL 54 DAY
and date_v_fin is null;
以下是我的“糟糕”查询的解释:
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)
以下是“好”优化查询的解释:
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)
答案 0 :(得分:2)
你基本上有两个问题:
目前无法使用date_v_creation
上的索引,因为比较是在字段值的函数而不是值本身。这就是date_v_creation
上的密钥没有帮助的原因。所以你应该按如下方式重写查询:
select date_v_creation
from devis
where etat=3
and date_v_creation < NOW() - INTERVAL 54 DAY
and date_v_fin is null;
答案 1 :(得分:0)
column is null
过滤掉smth,则应遵循以下策略(如果您确实需要它)。添加另一列is_null tinyint
。将其设置为1或0.在其上创建索引。etat
。此列的选择性(=不同的行/所有行)值是多少?如果它很低,创建B-Tree索引不会影响性能到高。理想的选择性为1,但只能通过NOT NULL
列上的唯一索引来达到这种选择性。答案 2 :(得分:0)
date_v_creation
未包含在您的索引中,因此MySQL仍然必须扫描表中的行才能执行SELECT。这是我的猜测,无论如何 - EXPLAIN SELECT...
会告诉你查询计划员正在做什么的细节。