如果我执行你上面所做的,我会得到
EXPLAIN select * from stats_clicked s
join visitor v on s.visitor_id=v.id
+----+-------------+-------+------+---------------+--------+---------+--------------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+--------+---------+--------------------+------+-------------+
| 1 | SIMPLE | v | ALL | PRIMARY | NULL | NULL | NULL | 15 | NULL |
| 1 | SIMPLE | s | ref | index3,index1 | index3 | 4 | so_gibberish2.v.id | 1 | Using index |
+----+-------------+-------+------+---------------+--------+---------+--------------------+------+-------------+
但是,如果我截断然后执行大量数据的以下加载(最终超过 100K 行):
truncate table visitor;
insert into visitor (`visited_time`) values
(1467122944),(1467122944),(1467122944),
(1467122944),(1467122944),(1467122944),
(1467122944),(1467122944),(1467122944),
(1467122944),(1467122944),(1467122944),
(1467122944),(1467122944),(1467122944);
insert into visitor (`visited_time`) values
(1467122945),(1467122945),(1467122945),
(1467122945),(1467122945),(1467122945),
(1467122945),(1467122945),(1467122945),
(1467122945),(1467122945),(1467122945),
(1467122945),(1467122945),(1467122945),
insert into visitor (`visited_time`) values
(1467122946),(1467122946),(1467122946),
(1467122946),(1467122946),(1467122946),
(1467122946),(1467122946),(1467122946),
(1467122946),(1467122946),(1467122946),
(1467122946),(1467122946),(1467122946),
(1467122946),(1467122946),(1467122946),
(1467122946),(1467122946),(1467122946),
(1467122946),(1467122946),(1467122946),
(1467122946),(1467122946),(1467122946),
(1467122946),(1467122946),(1467122946),
(1467122946),(1467122946),(1467122946),
(1467122946),(1467122946),(1467122946);
insert visitor(`visited_time`) select `visited_time` from visitor;
insert visitor(`visited_time`) select `visited_time` from visitor;
insert visitor(`visited_time`) select `visited_time` from visitor;
insert visitor(`visited_time`) select `visited_time` from visitor;
insert visitor(`visited_time`) select `visited_time` from visitor;
insert visitor(`visited_time`) select `visited_time` from visitor;
insert visitor(`visited_time`) select `visited_time` from visitor;
insert visitor(`visited_time`) select `visited_time` from visitor;
insert visitor(`visited_time`) select `visited_time` from visitor;
insert visitor(`visited_time`) select `visited_time` from visitor;
insert visitor(`visited_time`) select `visited_time` from visitor;
select count(*) from visitor;
-- 104448 rows
这导致不是表扫描:
EXPLAIN select * from stats_clicked s
join visitor v on s.visitor_id=v.id;
+----+-------------+-------+--------+---------------+---------+---------+----------------------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+---------+---------+----------------------------+------+-------------+
| 1 | SIMPLE | s | index | index3,index1 | index3 | 9 | NULL | 22 | Using index |
| 1 | SIMPLE | v | eq_ref | PRIMARY | PRIMARY | 4 | so_gibberish2.s.visitor_id | 1 | NULL |
+----+-------------+-------+--------+---------------+---------+---------+----------------------------+------+-------------+
原因在 Manual Page How MySQL Uses Indexes中列出:
对于小表或报表查询处理大部分或所有行的大表的查询,索引不太重要。当查询需要访问大部分行时,顺序读取比通过索引更快。即使查询不需要所有行,顺序读取也可以最大限度地减少磁盘寻道。
原因如上。在您的问题示例中,您的行数太少,无法使用索引。因此,数据库引擎选择了其所谓(并且可能)更快的方式,即不使用小表上的索引。