MySQL数据库索引详解

一、什么是索引:

  索引是一个排序的列表,在这个列表中存储着索引值和包含这个值的数据所在行的物理地址,在数据十分庞大的时候,索引可以大大加快查询速度,这是因为使用索引后可以不用全表扫描来定位某行的数据,而是先通过索引表找到该行数据对应的物理地址然后访问相应的数据。

  索引通过不断缩小想要获取数据的范围来筛选出最终想要的结果,同时把随机事件变成顺序事件,也就是说,有个这个机制我们可以总是用同一种查找方式来锁定数据;

  索引实际就是一张表,该表保存了主键和索引字段,并指向实体表的记录,所以索引也是占了一大部分空间,不可能存储在内存中,因此索引往往都是以文件形式存储在我们的硬盘上。

二、索引的分类:

常见索引有主键索引、唯一索引、普通索引、全文索引和组合索引。

1、主键索引

主索引,根据pk_clolum(length)建立索引,不允许重复,不允许空值;

ALTER TABLE 'table_name' ADD PRIMARY KEY pk_index('col');

2、唯一索引

用来建立索引的列的值必须是唯一的,允许空值;

ALTER TABLE ‘table_name' ADD UNIQUE index_name('col');

3、普通索引

用表中的普通列构建的索引,没有任何限制;

ALTER TABLE 'table_name' ADD INDEX index_name('col');

4、全文索引

用大文本对象的列构建的索引;

ALTER TABLE 'table_name' ADD INDEXD index_name('col');

5、组合索引

用多个列组合构建的索引,这多个列中的值不允许有空值;

ALTER TABLE 'table_name' ADD INDEX index_name('col');

三、SQL查询计划详解:

我们可以在select语句前添加explain来查询MySQL的执行计划,下面是对explain的具体说明:

id SELECT识别符。这是SELECT的查询序列号
select_type

查询类型

SIMPLE:简单的select(不使用UNION或子查询)

PRIMARY:最外面的select

UNION:UNION中第二个或后面的SELECT语句

DEPEDENT UNION:UNION中第二个或后面的SELECT语句,取决于外面的查询

UNION RESULT:UNION的结果

SUBQUERY:子查询中的第一个SELECT

DEPENDENT SUBQUERY:子查询中的第一个SELECT,取决于外面的查询

DERIVED:导出表的SELECT(FROM字句的子查询)

table 输出行所引用的表
type

联接类型

system:表仅有一行(=系统表)

const:表最多有一个匹配行,它将在查询开始时被读取。因为仅有一行,在这行的列值可被优化器剩余部分认为是常数。const表很快,因为它们只读取一次

eq_ref:对于每个来自前面的表的行组合,从该表中读取一行。这可能是最好的联接类型,除了const类型

ref:对于每个来自前面的表的行组合,所有有匹配索引值的行将从这张表中读取

ref_or_null:该联接类型同ref,但是添加了MySQL可以专门搜索包含NULL值的行

index_merge:该联接类型表示使用了索引合并优化方法

unique_subquery:该类型替换了下面形式的IN子查询的ref:value In (SELECT primary_key FROM single_table WHERE some_expr)unique_subquery是一个索引查找函数,可以完全替换子查询,效率更高

index_subquery:该联接类型类似于unique_subquery。可以替换IN子查询,但只适合下列形式的子查询中的非唯一索引:value IN (SELECT key_column FROM single_table WHERE some_expr)

rang:只检索指定范围的行,使用一个索引来选择行

index:该联接类型与ALL相同,除了只有索引树被扫描。这通常比ALL快,因为索引文件通常比数据文件小

ALL:对于每个来自先前的表的行组合,进行完整的表扫描

possible_keys 指出MySQL能使用哪个索引在该表中找到行
key 显示MySQL实际使用的键(索引)。如果没有选择索引,键是NULL
key_len 显示MySQL决定使用的键长度。如果没有选择索引,则长度为NULL
ref 显示使用哪个列或常数与key一起从表中选择行
rows 显示MySQL认为它执行查询时必须检查的行数。多行之间的数据相乘可以估算要处理的行数
filtered 显示了通过条件过滤出的行数的百分比估计值
Extra

MySQL解决查询的详细信息

Distinct:MySQL发现第1个匹配行后,停止为当前的行组合搜索更多的行

Not exists:MySQL能够对查询进行LEFT JOIN优化,发现1个匹配LEFT JOIN标准的行后,不再为前面的行组合在该表内检查更多的行

range checked for each record(index map:#):MySQL没有发现好的可以使用的索引,但发现如果来自前面的表的列值已知,可能部分索引可以使用

Using filesort:MySQL需要额外的一次传递,以找出如何按排序顺序检索行

Using index:从只使用索引树中的信息而不需要进一步索引读取实际的行来检索表中的列信息

Using temporary:为了解决查询,MySQL需要创建一个临时表来容纳结果

Using where:WHERE字句用于限制哪一个匹配下一个表或发送到客户

Using sort_union(...),Using union(...),Using intersect(...):这些函数说明如何为index_merge联接类型合并索引扫描

Using index for group-by:类似于访问表的Using index方式,Using index for group-by表示MySQL发现了一个索引,可以用来查询GROUP BY 或DISTINCT查询的所有列,而不要额外索引硬盘访问实际的表

type显示的是访问类型,是较为重要的一个指标,其中结果值从好到坏依次是:system>const>eq_ref>ref>fulltext>ref_or_null>index_merge>unique_subquery>index_subquery>range>index>ALL

一般我们在查询的时候至少保证到range级别,最后达到ref。

四、索引失效

1、前导模糊查询不能利用索引(like '%xxx' 或like '%xxx%')

2、使用or连接

3、使用不等号(!= 或者<>)

4、空值判断(is null 或者is not null)

5、varchar类型在条件查询时未加引号,导致隐式转换

6、查询所有(select *)

7、在索引列进行操作(计算、函数、类型转换),会导致索引失效转向全表扫描

8、使用not in 或者not exists

9、如果是左外连接或右外连接查询时,两张表的关联字段编码格式不一样

10、如果联合索引KEY 'name_index' ('name','code') Using BTREE没有用到第一个索引字段,则不会走索引

11、使用between and 

12、当变量是times类型,而字段是date类型,索引失效;或相反情况也一样失效

13、时间类型和varchar类型的索引比较

在这个列表中存储着索引的值和包含这个值的数据所在行的物理地址,在数据十分庞大的时候,索引可以大大加快查询的速度,这是因为使用索引后可以不用扫描全表来定位某行的数据,而是先通过索引表找到该行数据对应的物理地址然后访问相应的数据

索引通过不断地缩小想要获取数据的范围来筛选出最终想要的结果,同时把随机事件变成顺序事件,也就是说,有个这个机制我们可以总是用同一种查找方式来锁定数据;

索引实际就是一张表,该表保存了主键和索引字段,并指向实体表的记录,所以索引也是占了一大部分空间,不可能存储在内存中,因此索引往往都是以文件形式存储在硬盘上。

猜你喜欢

转载自www.cnblogs.com/afeng-chen/p/12195732.html