为了更好的理解连接类型(type),将根据查询条件的不同对连接类型进行简单归纳。
表定义如下:
1.id为主键
mysql> show create table key_id; +--------+----------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +--------+----------------------------------------------------------------------------------------------------------------------------------------------------------+ | key_id | CREATE TABLE `key_id` ( `id` char(128) NOT NULL DEFAULT '', `data` char(128) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 | +--------+----------------------------------------------------------------------------------------------------------------------------------------------------------+
2.id为unique索引
mysql> show create table key_id; +--------+---------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +--------+---------------------------------------------------------------------------------------------------------------------------------------------------------+ | key_id | CREATE TABLE `key_id` ( `id` int(11) NOT NULL DEFAULT '0', `data` char(128) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 | +--------+---------------------------------------------------------------------------------------------------------------------------------------------------------+
3.id为普通索引
mysql> show create table index_id; +----------+------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +----------+------------------------------------------------------------------------------------------------------------------------------------------------+ | index_id | CREATE TABLE `index_id` ( `id` int(11) DEFAULT NULL, `data` char(128) DEFAULT NULL, KEY`id` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 | +----------+------------------------------------------------------------------------------------------------------------------------------------------------+
一、等值查询:
1.const
mysql> explain extended select * fromkey_id where id='8'; +----+-------------+--------+-------+---------------+---------+---------+-------+------+----------+-------+ | id | select_type | table | type | possible_keys | key |key_len | ref | rows | filtered | Extra| +----+-------------+--------+-------+---------------+---------+---------+-------+------+----------+-------+ | 1| SIMPLE | key_id | const |PRIMARY | PRIMARY | 384 | const | 1 | 100.00 | NULL | +----+-------------+--------+-------+---------------+---------+---------+-------+------+----------+-------+
mysql> explain select id from key_id where id=4; +----+-------------+--------+-------+---------------+---------+---------+-------+------+-------------+ | id | select_type | table | type | possible_keys | key |key_len | ref | rows | Extra | +----+-------------+--------+-------+---------------+---------+---------+-------+------+-------------+ | 1| SIMPLE | key_id | const |PRIMARY | PRIMARY | 4 | const | 1 | Using index | +----+-------------+--------+-------+---------------+---------+---------+-------+------+-------------+
可以看到当unique和primary key索引被作为等值条件时触发。const非常快,在执行优化解析时值已经被算出来了。
2. ref
mysql> explain select * fromindex_id where id=2; +----+-------------+----------+------+---------------+------+---------+-------+------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+----------+------+---------------+------+---------+-------+------+-------+ | 1 |SIMPLE | index_id | ref | id | id | 5 | const | 1 | NULL | +----+-------------+----------+------+---------------+------+---------+-------+------+-------+
普通索引被作为等值条件时触发。
3.all
mysql> explain select * from index_id where data='a'; +----+-------------+----------+------+---------------+------+---------+------+------+-------------+ | id| select_type | table | type |possible_keys | key | key_len | ref | rows | Extra | +----+-------------+----------+------+---------------+------+---------+------+------+-------------+ | 1 | SIMPLE | index_id | ALL | NULL | NULL | NULL | NULL | 10 | Using where | +----+-------------+----------+------+---------------+------+---------+------+------+-------------+
当条件列没有任何索引的情况下触发。此时为全表搜索
二、范围查询
1.range
mysql> explain extended select * from key_id whereid>8; +----+-------------+--------+-------+---------------+---------+---------+------+------+----------+-------------+ | id | select_type | table | type | possible_keys | key |key_len | ref | rows | filtered | Extra | +----+-------------+--------+-------+---------------+---------+---------+------+------+----------+-------------+ | 1| SIMPLE | key_id | range |PRIMARY | PRIMARY | 4 | NULL | 2 | 100.00 | Using where | +----+-------------+--------+-------+---------------+---------+---------+------+------+----------+-------------+
可以看到当unique和primary key索引被作为范围查询条件时触发。而普通索引(根据经验)读取的数据不能超过表中数据的20%才触发,不然将会是全表搜索。
mysql> explain select * from index_id where id >9; +----+-------------+----------+-------+---------------+------+---------+------+------+-----------------------+ | id | select_type | table | type | possible_keys | key | key_len |ref | rows | Extra | +----+-------------+----------+-------+---------------+------+---------+------+------+-----------------------+ | 1| SIMPLE | index_id | range |id | id | 5 | NULL | 1 | Using indexcondition | +----+-------------+----------+-------+---------------+------+---------+------+------+-----------------------+
因为innodb通过索引来寻找数据时,首先会遍历辅助索引,然后根据辅助索引叶节点的指针获得主键索引的主键,最后再根据主键索引得到完整的行数据。并且辅助索引与主键索引不在同一个数据段,所以普通索引的访问是随机读的过程,当需要的数据量大时,通过普通索引搜索数据没有全表搜索这种顺序读来得快。
2.all
mysql> explain select * from index_id where data>'f'; +----+-------------+----------+------+---------------+------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+----------+------+---------------+------+---------+------+------+-------------+ | 1| SIMPLE | index_id | ALL | NULL | NULL | NULL | NULL | 10 | Using where | +----+-------------+----------+------+---------------+------+---------+------+------+-------------+
mysql> explain select * fromindex_id where id>2; +----+-------------+----------+------+---------------+------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+----------+------+---------------+------+---------+------+------+-------------+ | 1| SIMPLE | index_id | ALL | id | NULL | NULL |NULL | 6 | Using where | +----+-------------+----------+------+---------------+------+---------+------+------+-------------+
可以看出当条件列没有任何索引以及普通索引列获取数据的行数大于表中数据20%的情况下触发全表搜索。
三、不带条件
1.index
mysql> explain extended select id fromkey_id; +----+-------------+--------+-------+---------------+---------+---------+------+------+----------+-------------+ | id | select_type | table | type | possible_keys | key |key_len | ref | rows | filtered |Extra | +----+-------------+--------+-------+---------------+---------+---------+------+------+----------+-------------+ | 1| SIMPLE | key_id | index |NULL | PRIMARY | 384 | NULL | 4 | 100.00 | Using index | +----+-------------+--------+-------+---------------+---------+---------+------+------+----------+-------------+
可以看到当查询的列为索引列将触发index。此时只需要对索引页进行遍历。
2.all
mysql> explain extended select * fromkey_id; +----+-------------+--------+------+---------------+------+---------+------+------+----------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+--------+------+---------------+------+---------+------+------+----------+-------+ | 1| SIMPLE | key_id | ALL | NULL | NULL | NULL | NULL | 5 | 100.00 | NULL | +----+-------------+--------+------+---------------+------+---------+------+------+----------+-------+
当查询字段有未加非索引的情况则需要遍历整张表。