一、不同索引
1.1索引介绍
索引分单列索引和组合索引。单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。组合索引,即一个索包含多个列。创建索引时,你需要确保该索引是应用在SQL 查询语句的条件(一般作为WHERE 子句的条件)。实际上,索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录。
上面都在说使用索引的好处,但过多的使用索引将会造成滥用。因此索引也会有它的缺点:虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。建立索引会占用磁盘空间的索引文件。
1.2索引分类
1、普通索引,即默认的B-TREE索引方式。
2、唯一索引unique index,它与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。
3、Hash索引,只有memory引擎支撑,适用场景也比较简单。
4、Full-text全文索引,只要用于全文索引,mysql5.6开始提供该索引支持。
MyISAM、InnoDB引擎、Memory三个常用引用类型比较
索引 MyISAM引擎 InnoDB引擎 Memory引擎
B-Tree索引 支持 支持 支持
HASH索引 不支持 不支持 不支持
R-Tree索引 支持 不支持 不支持
Full-text索引 不支持 暂不支持 不支持
B_TREE索引类型
1》 普通索引
这是最基本的索引类型,而且它没有唯一性之类的限制。可以通过以下方式建立:
(A) 创建索引:create index index_name on tb_name (col1,col2,…);
(B) 修改表:alter table tb_name add index index_name(col1,col2,…);
(C) 创建表时指定索引:create table tb_name([…],index index_name(col1,col2,…));
2》 UNIQUE索引
表示唯一的,不允许重复的索引,如果该字段信息保证不会重复,可设置问哦unique
(A) 创建索引:create unique index index_name on tb_name (col1,col2,…);
(B) 修改表:alter table tb_name add unique index_name(col1,col2,…);
(C) 创建表时指定索引:create table tb_name([…],unique index_name(col1,col2,…));
3》 主键:PRIMARY KEY索引
主键是一种唯一性索引,但它必须指定“PRIMARY KEY”。
(A) 主键一般在创建表的时候指定:“create table tb_name([…],primary key(col1,col2,…))”。
(B) 但是,我们也可以通过修改表的方式加入主键:“alter table tb_name add primary key(col1,col2,…))”。每个表只能有一个主键。(主键相当于聚合索引,是查找最快的索引)
注意:不能用create index语句创建primary key索引
显示索引信息
Mysql>show index from tb_name G
二、索引的适用环境
一) 索引选择原则
1、 较频繁的作为查询条件的字段应该创建为索引
2、 唯一性太差的字段不适合,即使频繁作为查询条件
3、 更新非常频繁的字段不适合创建索引
当然,并不是存在更新的字段就适合创建索引,从判定策略的用语上可以看出,是“非常频繁“的字段。到底什么样的更新频率应该算是”非常频繁“呢?很多时候是通过比较同一时间段内被更新的次数和利用该字段作为条件的查询次数来判断的,如果通过该字段的查询并不是很多,可能几个小时或更长才会执行一次,更新反而比查询更频繁,那这样的字段肯定不适合创建索引。反之,如果我们通过该字段的查询比较频繁,但更新并不是特别多,比如查询几十次或更多次才可能会产生一次更新,那个人认为更新所带来的附加成本也是可以接受的。
4、 不会出现在where子句中的字段不该创建索引
二) 索引选择原则细诉
1、 在性能优化过程中,选择在哪个列上创建索引是非常重要的。可以考虑使用索引的主要有2种类型的列:在where子句中的列,在join子句中出现的列,而不是在select关键字后选择列表的列;
2、 索引列的基数越大,索引效果越好。比如出生日期。反之“性别“则对此进行索引没有多大用处,因不管搜索哪个值,都会得到大约一半的行;
3、 使用短索引,如果对字符串列进行索引,应该指定一个前缀长度,可节省大量索引空间,提升查询速度。
三) 索引选择注意事项
既然索引可以加快查询速度,那么是不是只要查询语句需要就建索引?NO。因为索引虽然加快了查询速度,但索引也是有代价的:索引文件本身要消耗存储空间,同时索引会加重插入、删除和修改记录时的负担,另外,MySQL在运行时也要消耗资源维护索引,因此索引并不是越多越好。
一般两种情况下不建议建索引:
1) 表中记录较少。例如一两千条甚至几百条记录的表,没必要建,做全表扫描就ok。(个人认为以2000作为分界线);
2) 索引的选择性较低。所谓索引的选择性,是指不重复的索引值与表记录的比值。显然选择性的取值范围为(0,1),选择性越高的索引价值越大,这是由B+Tree的性质决定的。
3) Mysql只对以下操作符才使用索引:<,<=,=,>,>=,between,in,以及某些时候的like(不以通配符%或_开头的情形)。
4) 不要过度索引,只保持所需要的索引。每个额外的索引都要占用额外的磁盘空间,并降低写操作的性能。在修改表的内容时,索引必须进行更新,有时可能需要重构,因此,索引越多,所花的时间越长。
索引创建规则:
1、表的主键、外键必须有索引;
2、数据量超过300的表应该有索引;
3、经常与其他表进行连接的表,在连接字段上应该建立索引
4、经常出现在Where子句中的字段,特别是大表的字段,应该建立索引;
5、索引应该建在选择性高的字段上;
6、索引应该建在小字段上,对于大的文本字段甚至超长字段,不要建索引;
7、复合索引的建立需要进行仔细分析;尽量考虑用单字段索引代替:
A、正确选择复合索引中的主列字段,一般是选择性较好的字段;
B、复合索引的几个字段是否经常同时以AND方式出现在Where子句中?单字段查询是否极少甚至没有?如果是,则可以建立复合索引;否则考虑单字段索引;
C、如果复合索引中包含的字段经常单独出现在Where子句中,则分解为多个单字段索引;
D、如果复合索引所包含的字段超过3个,那么仔细考虑其必要性,考虑减少复合的字段;
E、如果既有单字段索引,又有这几个字段上的复合索引,一般可以删除复合索引;
8、频繁进行数据操作的表,不要建立太多的索引;
9、删除无用的索引,避免对执行计划造成负面影响; 以上是一些普遍的建立索引时的判断依据。
一言以蔽之,索引的建立必须慎重,对每个索引的必要性都应该经过仔细分析,要有建立的依据。因为太多的索引与不充分、不正确的索引对性能都毫无益处:在表上建立的每个索引都会增加存储开销,索引对于插入、删除、更新操作也会增加处理上的开销。另外,过多的复合索引,在有单字段索引的情况下,一般都是没有存在价值的;相反,还会降低数据增加删除时的性能,特别是对频繁更新的表来说,负面影响更大。