非常奇怪如下:
mysql> explain select *from online where last < now()-interval 30 second and type=1;
+----+-------------+--------+------+---------------------------------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+------+---------------------------------------+------+---------+------+------+-------------+
| 1 | SIMPLE | online | ALL | i_online_type_last,i_online_last_type | NULL | NULL | NULL | 24 | Using where |
+----+-------------+--------+------+---------------------------------------+------+---------+------+------+-------------+
mysql> explain select *from online where last < '2009-06-16 06:48:33' and type=1;
+----+-------------+--------+------+---------------------------------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+------+---------------------------------------+------+---------+------+------+-------------+
| 1 | SIMPLE | online | ALL | i_online_type_last,i_online_last_type | NULL | NULL | NULL | 120 | Using where |
+----+-------------+--------+------+---------------------------------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
mysql> show index from online;
+--------+------------+--------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+--------+------------+--------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| online | 0 | PRIMARY | 1 | id | A | 24 | NULL | NULL | | BTREE | |
| online | 0 | account_id | 1 | account_id | A | 24 | NULL | NULL | | BTREE | |
| online | 1 | i_online_type_last | 1 | last | A | 2 | NULL | NULL | YES | BTREE | |
| online | 1 | i_online_type_last | 2 | type | A | 2 | NULL | NULL | | BTREE | |
| online | 1 | i_online_last_type | 1 | last | A | 2 | NULL | NULL | YES | BTREE | |
| online | 1 | i_online_last_type | 2 | type | A | 2 | NULL | NULL | | BTREE | |
+--------+------------+--------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
6 rows in set (0.00 sec)
对于那些因为桌子大小而说的人:
mysql> explain select *from users where email='test@gmail.com';
+----+-------------+-------+-------+---------------+---------------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------------+---------+-------+------+-------+
| 1 | SIMPLE | users | const | u_users_email | u_users_email | 386 | const | 1 | |
+----+-------------+-------+-------+---------------+---------------+---------+-------+------+-------+
1 row in set (0.00 sec)
mysql> select count(*) from users;
+----------+
| count(*) |
+----------+
| 24 |
+----------+
1 row in set (0.00 sec)
以下是一些更多线索:
mysql> explain select * from online where `last` > '2009-06-16 06:48:33' and type in (1,2);
+----+-------------+--------+-------+--------------------+--------------------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+-------+--------------------+--------------------+---------+------+------+-------------+
| 1 | SIMPLE | online | range | i_online_type_last | i_online_type_last | 13 | NULL | 2 | Using where |
+----+-------------+--------+-------+--------------------+--------------------+---------+------+------+-------------+
1 row in set (0.00 sec)
mysql> explain select * from online where `last` < '2009-06-16 06:48:33' and type in (1,2);
+----+-------------+--------+------+--------------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+------+--------------------+------+---------+------+------+-------------+
| 1 | SIMPLE | online | ALL | i_online_type_last | NULL | NULL | NULL | 120 | Using where |
+----+-------------+--------+------+--------------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
更改'&lt;'到'&gt;'会让它完全不同,为什么?
最后我发现了修复,因为last
的默认值为“null”,将此列更改为“not null”会使索引工作。
但是我不知道为什么这会让它变得不同,有什么解释吗?
答案 0 :(得分:1)
24行不足以让优化者烦恼。你需要用更大的表进行测试。
答案 1 :(得分:0)
now()-interval 30 second
的引用删除为日期文字。我看到他们扔掉了索引。这是我还是你有两个完全相同的索引?
答案 2 :(得分:0)
我已经看到MySQL中的查询优化器通过索引选择做了一些奇怪的事情,并且通常找到修复的唯一方法是通过反复试验。有几件事要尝试(不保证他们可能有所帮助):
i_online_*
);保留第一列具有更高特异性的那一个(可能是last
作为第一列的那个)。last
列NOT NULL
是否有所不同(使用最小日期而不是null
)。now() ...
表达式。尝试使用之前设置的变量。查看表格的整个架构也会有所帮助;也许有一些奇怪的副作用要发现?