MySQL的索引(索引的创建和设计原则):
目录
索引的创建:
索引的概念和创建和查看以及删除语法格式:
普通索引:
创建索引:
查看索引:
删除索引:
唯一性索引:
创建索引:
查看索引:
删除索引:
主键索引:
创建索引:
查看索引:
删除索引:
单列索引:
创建索引:
查看索引:
删除索引:
多列索引:
创建索引:
查看索引:
删除索引:
隐藏索引:
创建隐藏索引:
修改索引的可见性:
索引的设计原则:
适合创建索引的情况:
字段的数值有唯一性的限制:
频繁作为where查询条件的字段:
经常group by和order by的字段:
update、delete的where条件:
distinct字段需要创建索引:
多表join连接操作时:
适用类型小的创建索引:
使用字符串前缀创建索引:
区分度高(散列性高)的列适合作为索引:
使用最频繁的列放到联合索引的左侧:
多个字段都要创建索引的情况下,联合索引优于单列索引
索引的数目:
不适合创建索引的情况:
数据量小的表不创建索引:
有大量重复数据的列不创建索引:
避免对经常更新的表创建过多的索引:
不建议用无序的值作为索引:
删除不再使用或者很少的索引:
不要定义冗余或者重复的索引:
MySQL的索引包括主键索引、唯一性索引、普通索引、单列索引、多列索引、全文索引和空间索引。
主要对主键索引、唯一性索引、普通索引、单列索引、多列索引进行讲解。
索引的创建:
MySQL支持在单个列或者多个列上创建索引,在创建表时使用create table中指定索引列,或者使用alter table语句在已有的表上创建索引,再或者使用create index语句在已有表上添加索引。
create table 表名(字段名 数据类型 约束,...
);
create table 表名[字段名 数据类型]
[UNIQUE|FULLTEXT|SPATIAL] [INDEX|KEY] [索引名](字段名[索引长度]
)[ASC|DESC];INDE
UNIQUE、FULLTEXT和SPATIAL:分别表示唯一索引、全文索引和空间索引。
INDEX和KEY:作用相同,指定创建索引。
如果未指定索引名,那么默认索引名为字段名。
索引长度只有字符串类型才能指定索引长度。
ASC、DESC:指定升序或者降序的索引值存储。
索引的概念和创建和查看以及删除语法格式:
普通索引:
在创建普通索引时,不附加任何限制条件,只是用于提高查询效率。可以创建在任何数据类型中,其值是否唯一和非空,由字段本身的完整性约束条件决定。建立索引之后,可以通过索引进行查询。
创建索引:
create table 表名(字段名 数据类型,...INDEX 索引名(字段名)
);
alter table 表名
add index 索引名(字段名);
create index 索引名 on 表名(字段名);
查看索引:
show create table 表名;
或者
show index from 表名;
删除索引:
alter table 表名 drop index 索引名;
drop index 索引名 on 表名;
唯一性索引:
使用UNIQUE可以设置索引为唯一性索引,在创建唯一性索引时,限制该索引的值必须是唯一的,但是允许有空值,一张表中可以有多个唯一索引。
创建索引:
create table 表名(字段名 数据类型,...UNIQUE INDEX 索引名(字段名)
);
alter table 表名
add unique 索引名(字段名);
create unique index 索引名 on 表名(字段名);
查看索引:
show create table 表名;
或者
show index from 表名;
删除索引:
alter table 表名 drop index 索引名;
drop index 索引名 on 表名;
添加了auto_increment约束字段的唯一索引不能被删除。
主键索引:
是一种特殊的唯一性索引,在唯一索引的基础上增加了不为空的约束,一张表中只能有一个主键索引。
创建索引:
create table 表名(字段名 数据类型 PRIMARY KEY [AUTO_INCREMENT],...
);
查看索引:
show create table 表名;
或者
show index from 表名;
删除索引:
alter table 表名 drop index 索引名;
drop index 索引名 on 表名;
添加了auto_increment约束字段的唯一索引不能被删除。
单列索引:
在表中的单个字段上创建索引。一张表可以有多个单列索引。
以唯一索引做演示:
创建索引:
create table 表名(字段名 数据类型,...UNIQUE INDEX 索引名(字段名);
);
alter table 表名
add unique 索引名(字段名);
create unique index 索引名 on 表名(字段名);
查看索引:
show create table 表名;
或者
show index from 表名;
删除索引:
alter table 表名 drop index 索引名;
drop index 索引名 on 表名;
多列索引:
在表的多个字段上创建一个索引。使用组合索引时遵循最左前缀集合。
以普通索引演示:
创建索引:
create table 表名(字段名 数据类型,...INDEX 索引名(字段名1,字段名2,...)
);
alter table 表名
add index 索引名(字段名1,...);
create index 索引名 on 表名(字段名1,...);
查看索引:
show create table 表名;
或者
show index from 表名;
删除索引:
alter table 表名 drop index 索引名;
alter table 表名 drop index 索引名;
隐藏索引:
MySQL8.0开始支持隐藏索引,将待删除的索引设置为隐藏索引,使查询优化器不再使用这个索引,如果设置为隐藏索引后系统不受任何影响,就可以删除索引。可以避免显式删除之后出现错误重新创建索引时消耗过多的资源。
逐渐不能设置为隐藏索引,如果没有主键,第一个唯一非空索引会成为隐式主键,也不能设置为隐藏索引。
索引默认是可见的,可以通过visible和invisible关键词设置索引的可见性。
创建隐藏索引:
create table 表名(字段名 数据类型,index 索引名(字段名) invisible
);
alter table 表名
add index 索引名(字段名) invisible;
create index 索引名 on 表名(字段名) invisible;
修改索引的可见性:
alter table 表名
alter index 索引名 invisible;可见改为不可见
alter table 表名
alter index 索引名 visible;不可见改为可见
当索引被隐藏时,内容仍然适合正常索引一样实时更新的。
索引的设计原则:
适合创建索引的情况:
字段的数值有唯一性的限制:
索引本身可以起到约束的作用,因此在数据表中,如果某个字段是唯一性的,可以直接创建唯一性索引或者主键索引,能够更好地通过该索引确定某条记录。
频繁作为where查询条件的字段:
在数据量大的情况下,创建普通索引就可以大幅度提升数据查询的效率。
经常group by和order by的字段:
索引就是让数据按照某种顺序进行存储或者检索,如果使用group by或者order by就需要对分组或者排序的字段进行索引。
对于group by和order by一起进行时,可以分别对相应的列创建索引,也可以使用联合索引。一般使用联合索引,将group by后的字段写在联合索引前面,order by后的字段写在联合索引后面,这样相较于效率更高。
update、delete的where条件:
对数据按照某个条件进行查询后再进行update或者delete,对where字段创建索引,能够大幅提升效率。因为需要先根据where条件列检索出来的记录,然后进行更新或者删除,如果进行更新时,更新的字段是非索引字段,提升的效率会更明显,因为非索引字段更新不需要对索引进行维护。
distinct字段需要创建索引:
需要对某个字段进行去重时,可以对这个字段创建索引,能够提升查询效率。
多表join连接操作时:
连接表的数量尽量不超过3张,因为增加一张表相当于嵌套了一层循环,严重影响查询的效率。对where条件创建索引。对用于连接的字段创建索引,并且该字段在多张表中的类型一致。
适用类型小的创建索引:
想对某个列创建索引,尽量让索引使用较小的类型。因为数据类型越小,查询时进行得比较操作越快,索引占用的存储空间也会更少,一个数据也就能存储更多记录,进而可以减少磁盘I/O带来的性能损耗。
对于主键更加适用,因为不仅聚簇索引中会存储主键值,非聚簇索引的节点都会存储一份记录的主键值,如果主键值的类型越小,就能节省更多的存储空间和更高效的I/O。
使用字符串前缀创建索引:
B+树索引中的记录需要把该列的完整字符串存储起来,字符串越长的话,索引中占用的存储空间越大,还更费时。
B+树种索引中索引列存储的字符串很长,会导致在比较时消耗的时间更多。
通过截取字段前面的一部分内容建立索引,也就是前缀索引。虽然不能精确的定位,但能定位到相应的前缀所在的位置,然后根据前缀相同的记录的主键值回表查询到完整的字符串。前缀索引节约了空间又减少了字符串的比较时间,还大体能解决排序的问题。
根据区分度来选择索引的长度。
区分度:
count(distinct left(字段名,索引长度))/count(*)
使用前缀索引之后无法支持索引排序,只能使用文件排序。
区分度高(散列性高)的列适合作为索引:
列的基数是指某一列中不重复的数据的个数。在记录行数一定的情况下,列的基数越大,该列中的值越分散,相反列的基数越小,该列中的值越集中。
区分度:
count(distinct 字段名)/count(*)
区分度越接近1越好。
在联合索引中,把区分度高的列放在前面。
使用最频繁的列放到联合索引的左侧:
这样可以相对创建较少的索引。由于“最左前缀原则”,可以增加联合索引的使用率。
多个字段都要创建索引的情况下,联合索引优于单列索引
索引的数目:
索引不是越多越好,需要限制每张表上的索引数,一般不超过6个。
因为每个索引都需要占用磁盘,索引越多,需要的磁盘空间就越大。
索引会影响增删改操作的效率,因为要进行维护索引,造成性能消耗。
优化器在选择时,会对每一个可以用到的索引进行评估,所以同时有很多个索引都能用于查询,会增加优化器生成执行计划,导致查询性能降低。
不适合创建索引的情况:
where中使用不到的字段,不设置索引:
因为起不到快速定位的字段不需要创建索引。
数据量小的表不创建索引:
因为数据量小的话,查询花费的时间与是否创建索引并没太大关系。
有大量重复数据的列不创建索引:
重复的数据太多,如果创建索引,无法快速的进行定位,会降低数据更新的速度。
避免对经常更新的表创建过多的索引:
频繁更新的字段不一定要创建索引,因为更新数据时,索引也会更新,造成性能损耗。
经常更新的表创建过多的索引,更新时会大大降低更新表的速度。
不建议用无序的值作为索引:
当使用无序的列作为索引时,B+树索引时一个有序的,会按照主键的大小进行排序,可能会导致页分裂,数据的转移。
删除不再使用或者很少的索引:
能够减少索引对更新操作的影响。
不要定义冗余或者重复的索引:
对同一个列创建了多个索引,会导致只使用该列的一个索引,而其他的索引就是冗余的索引,不仅增加了存储空间的浪费,还会增加维护的成本。
对同一个列创建了重复的索引,如主键值创建了唯一索引,还定义了普通索引,主键值本身就会生成聚簇索引,唯一索引和普通索引就是重复的。