赞
踩
理解了索引的原理,我们先来看一下单表的查询。
表结构如下:
CREATE TABLE single_table (
id INT NOT NULL AUTO_INCREMENT,
key1 VARCHAR(100),
key2 INT,
key3 VARCHAR(100),
key_part1 VARCHAR(100),
key_part2 VARCHAR(100),
key_part3 VARCHAR(100),
common_field VARCHAR(100),
PRIMARY KEY (id),
KEY idx_key1 (key1),
UNIQUE KEY idx_key2 (key2),
KEY idx_key3 (key3),
KEY idx_key_part(key_part1, key_part2, key_part3)
) Engine=InnoDB CHARSET=utf8;
const
SELECT * FROM single_table WHERE id = 1438;
id是聚簇索引
SELECT * FROM single_table WHERE key2 = 3841;
ref
SELECT * FROM single_table WHERE key1 = 'abc
ref_or_null
SELECT * FROM single_table WHERE key1 = 'abc' OR key1 IS NULL;
range
SELECT * FROM single_table WHERE key2 IN (1438, 6328) OR (key2 >= 38 AND key2 <= 79);
index
看下边这个查询:
SELECT key_part1, key_part2, key_part3 FROM single_table WHERE key_part2 ='abc';
由于key_part2并不是联合索引idx_key_part最左索引列,所以我们无法使用ref或者range访问方法来执行这个语句。但是这个查询符合下边这两个条件:
它的查询列表只有3个列:key_part1, key_part2, key_part3,而索引idx_key_part又包含这三个列。
搜索条件中只有key_part2列。这个列也包含在索引idx_key_part中。
也就是说我们可以直接通过遍历idx_key_part索引的叶子节点的记录来比较key_part2 = 'abc'这个条件是否成立,把匹配成功的二级索引记录的key_part1, key_part2, key_part3列的值直接加到结果集中就行了。由于二级索引记录比聚簇索记录小的多(聚簇索引记录要存储所有用户定义的列以及所谓的隐藏列,而二级索引记录只需要存放索引列和主键),而且这个过程也不用进行回表操作,所以直接遍历二级索引比直接遍历聚簇索引的成本要小很多,设计MySQL的大叔就把这种采用遍历二级索引记录的执行方式称之为:index。
all
全表扫描
多个表查询
一个表查询使用索引飞快,那么如果是多个表呢,先说两个表吧。
如果没有任何条件,两个表关联查询要进行连接,正常情况是笛卡尔积。链接的数量是两个表数量的乘积,这是非常可怕的数字,所以我们一般都会增加where过滤条件,这样就会减少链接的数量,具体是怎么实现的。
是不是听过大表驱动小表。 当两个表关联时,有一个表是驱动表,从驱动表取出所有N条数据,要拿着这N条的每一条去被驱动表查询数据,所以关联的数量是 驱动表筛选出的数据 * 被驱动表的数量,如果被驱动表很大,这个速度就很慢了,所以尽量减少被驱动表的数量还是有必要的。
但是被驱动表的查询如果能用上索引就很快了,所以关联条件最好与索引,这样可以极大的提高效率。
这样查询的时候,驱动表的数据使用索引,扫描少量数据快速定位, 被驱动表使用驱动表的数据,按照索引,快速搜索出数据, 两次的数据量都很少,这样就能提高查询效率。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。