写点什么

MySQL 数据库之索引

作者:Java快了!
  • 2022 年 9 月 15 日
    湖南
  • 本文字数:4562 字

    阅读完需:约 15 分钟

目录

三.创建索引的原则依据

4.组合索引(单列索引与多列索引)

5. 全文索引(FULLTEXT)

一.索引概述

MySql 官方对索引的定义为:索引是帮助 MySql 高效获取数据的数据结构。在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用数据,这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引。

个人对于 MySql 索引的理解:在数据之外,数据库系统还维护着满足特定查找算法的数据结构,包括 B+树或者 Hash 表。由于存储引擎表示的是数据在磁盘上面的不同的组织形式,所以索引底层采用哪种数据结构是跟数据库的存储引擎相关的。如果是 MyIsam 或者是 InnoDB 存储引擎,那么对应的底层的数据结构为 B+树,如果是 Memory 存储引擎,那么对应的底层的数据结构为 Hash 表。采用 B+树的最根本的原因是由于二叉树的树太高,树太高则直接影响到磁盘 IO 的次数,影响数据查询的效率,采用 B+树的数据结构,可以在某个数据节点里面尽可能多的存储数据,使树的高度尽量的变低,提高效率。日常开发过程中,遇到的比较多的可能就是聚簇索引和联合索引,里面又涉及到了覆盖索引,最左匹配,回表,索引下推等各方面的知识点,在编写 SQL 语句的时候,我们就可以利用这些点来进行优化,提高数据的查询效率。

索引是数据库优化最常用也是最重要的手段之一,通过索引通常可以帮助用户解决大多数的 MySql 的性能优化问题。

总结:做 MySQL 索引目的即为优化

二.索引作用的优缺点

1.优点

类似于书籍的目录索引,提高数据检索的效率,降低数据库的 IO 成本。

通过索引列对数据进行排序,降低数据排序的成本,降低 CPU 的消耗。

2.缺点

实际上索引也是一张表,该表中保存了主键与索引字段,并指向实体类的记录,所以索引列也是要占用空间的。

虽然索引大大提高了查询效率,同时却也降低更新表的速度,如对表进行 INSERT、 UPDATE、 DELETE。因为更新表时,MSQL 不仅要保存数据,还要保存一下索引文件每次更新添加了索引列的字段,都会调整因为更新所带来的键值变化后的索引信息。

三.创建索引的原则依据

索引随可以提升数据库查询的速度,但并不是任何情况下都适合创建索引。因为索引本身会消耗系统资源,在有索引的情况下,数据库会先进行索引查询,然后定位到具体的数据行,如果索引使用不当,反而会增加数据库的负担。

1.表的主键、外键必须有索引。因为主键具有唯一性,外键关联的是子表的主键,查询时可以快速定位。

2.记录数超过 300 行的表应该有索引。如果没有索引,需要把表遍历一遍,会严重影响数据库的性能。

3.经常与其他表进行连接的表,在连接字段上应该建立索引。

4.唯一性太差的字段不适合建立索引。

5.更新太频繁地字段不适合创建索引。

6.经常出现在 where 子句中的字段,特别是大表的字段,应该建立索引。

7.索引应该建在选择性高的字段上。

8.索引应该建在小字段上,对于大的文本字段甚至超长字段,不要建索引。

四.适用索引的场景

1.频繁作为 WHERE 查询条件的字段

某个字段在 SELECT 语句的 WHERE 条件中经常被使用到,那么就需要给这个字段创建索引了。尤其是在数据量大的情况下,创建索引就可以大幅提升数据查询的效率。

2. 有唯一性限制的字段

字段的值是唯一值的时候优先考虑加上索引,索引本身也可以起到约束作用,且唯一索引查询的速度会比普通索引更快速。

3.经常 GROUP BY 和 ORDER BY 的列

索引已经将数据排好序了,因此当我们使用 GROUP BY 对数据进行分组查询,或者使用 ORDER BY 对数据进行排序的时候,通过索引就可以十分快速(避免了排序操作) 。如果待排序的列有多个,那么可以在这些列上建立联合索引 。

4.UPDATE、DELETE 的 WHERE 条件列

对数据按照某个条件进行查询后再进行 UPDATE 或 DELETE 的操作,如果对 WHERE 字段创建了索引,就能大幅提升效率。原理是因为我们需要先根据 WHERE 条件列检索出来这条记录,然后再对它进行更新或删除。如果进行更新的时候,更新的字段是非索引字段,提升的效率会更明显,这是因为非索引字段更新不需要对索引进行维护。

5.DISTINCT 字段需要创建索引

有时候我们需要对某个字段进行去重,使用 DISTINCT,那么对这个字段创建索引,也会提升查询效率。

6.多表 JOIN 连接操作时

对 WHERE 条件创建索引 ,因为 WHERE 才是对数据条件的过滤。

其次,对用于连接的字段创建索引,并且该字段在多张表中的类型必须一致 。比如 course_id 在 student_info 表和 course 表中都为 int(11) 类型,而不能一个为 int 另一个为 varchar 类型。

7. 使用列的类型小的创建索引

类型表示的范围越小:

查询时进行的比较操作越快

索引占用的空间越小,在一个数据页能存放更多的记录,树的高低相对偏低

8.使用字符串前缀创建索引

理由和前一点相同。

截取字段的前一部分内容建立索引,叫做前缀索引。这样在查找时虽然不能精确定位,但是能定位到相应前缀所在位置,然后根据前缀相同记录的主键值回表查询完整的字符串值。节约空间,又减少了字符串的比较时间。

9.区分度高(散列性高)的列适合作为索引

比如性别字段,区分度很低,不建议使用索引。一般区分比超过 33%即可。

10.使用最频繁的列放到联合索引的左侧

这样也可以较少的建立一些索引。同时,由于"最左前缀原则",可以增加联合索引的使用率。

11.在多个字段都要创建索引的情况下,联合索引优于单值索引

这种情况下,尽可能建立联合索引。

五.索引的分类和创建

create table team (id int(10),name varchar(10),cardid varchar(18),phone varchar(11),

address varchar(50),hobby text);

insert into team values (1,'yz','250','5438','beijing','打游戏');

insert into team values (2,'lnj','110','5439','nanjing','背刺');

insert into team values (3,'zwb','666','9527','shenzhen','打篮球');

insert into team values (4,'szh','333','5440','hangzhou','打羽毛球');

insert into team values (5,'ls','555','5445','shanghai','踢足球');





1.普通索引

1.1 直接创建索引

CREATE INDEX 索引名 ON 表名 (列名[(length)]);

(列名(length)):length 是可选项。如果忽略 length 的值,则使用整个列的值作为索引。如果指定使用列前的 length 个字符来创建索引,这样有利于减小索引文件的大小。

索引名建议以“_index”结尾。

create index cardid_index on team (cardid);



show create table team;



1.2 修改表方式创建

ALTER TABLE 表名 ADD INDEX 索引名 (列名);

alter table team add index phone_index (phone);

select phone from team;

select phone,name from team;

show create table team\G





1.3 创建表的时候指定索引

CREATE TABLE 表名 ( 字段 1 数据类型,字段 2 数据类型[,...],INDEX 索引名 (列名));

create table test(id int(4) not null,name varchar(10) not null,age int (3),cardid varchar(5) not null,index age_index(age));

show create table test;



2.唯一索引

CREATE UNIQUE INDEX 索引名 ON 表名(列名);

select * from team;

create unique index address_index on team (address);

create unique index name_index on team (name);

show create table team\G




3.修改表方式创建

ALTER TABLE 表名 ADD UNIQUE 索引名 (列名);

alter table team add unique id_index (id);



3.1 CREATE TABLE 表名 ([...],PRIMARY KEY (列名));

create table lcdb1 (id int primary key,name varchar(20));

create table lcdb2 (id int,name varchar(20),primary key (id));

show create table lcdb1\G

show create table lcdb2\G



3.2 修改表方式创建

ALTER TABLE 表名 ADD PRIMARY KEY (列名);

alter table lcdb6 add primary key(name);



这里切记做主键索引的时候不能存在其他主键要么删除主键

4.组合索引(单列索引与多列索引)

可以是单列上创建的索引,也可以是在多列上创建的索引。需要满足最左原则,因为 select 语句的 where 条件是依次从左往右执行的,所以在使用 select 语句查询时 where 条件使用的字段顺序必须和组合索引中的排序一致,否则索引将不会生效。

CREATE TABLE 表名 (列名 1 数据类型,列名 2 数据类型,列名 3 数据类型,INDEX 索引名 (列名 1,列名 2,列名 3));

select * from 表名 where 列名 1='...' AND 列名 2='...' AND 列名 3='...';

create table lcdb2 (id int(4),name char(30),genter char(10),age int(4),height decimal(3,1),address char(100),index index_group(id,name));

show create table lcdb\G

insert into lcdb7 values(1,'lnj','男',21,90,'南京');

select * from lcdb2 where name='zhangsan' and id=1;




组合索引创建的字段顺序是其触发索引的查询顺序

select id,name from test3;                 #会触发组合索引

select name,id from test3;                 #按照索引从左到右检索的顺序,则不会触发组合索引



5. 全文索引(FULLTEXT)

适合在进行模糊查询的时候使用,可用于在一篇文章中检索文本信息。

在 MySQL5.6 版本以前 FULLTEXT 索引仅可用于 MyISAM 引擎,在 5.6 版本之后 innodb 引擎也支持

FULLTEXT 索引。全文索引可以在 CHAR、VARCHAR 或者 TEXT 类型的列上创建。每个表只允许有一个全文索引。

5.1 直接创建全文索引

CREATE FULLTEXT INDEX 索引名 ON 表名 (列名);

select * from team;

create fulltext index suoyin on team(cardid);

desc team;




5.2 修改表方式创建

ALTER TABLE 表名 ADD FULLTEXT 索引名 (列名);

alter table team add fulltext index suoyin_index(name);

desc team;



CREATE TABLE 表名 (字段 1 数据类型[,...],FULLTEXT 索引名 (列名));

#数据类型可以为 CHAR、VARCHAR 或者 TEXT

create table lcdb8(id int(4),name char(10),genter char(2), age int(2),address char(20

),fulltext index suoyin_index(address));

desc lcdb8;



5.4 使用全文索引查询

SELECT * FROM 表名 WHERE MATCH(列名) AGAINST('查询内容');

select * from team where match(name) against('lnj');

select * from member where name='lnj';



六、查看索引

show index from 表名;

show index from 表名\G; 竖向显示表索引信息

show keys from 表名;

show keys from 表名\G;

Table                   表的名称

Non_unique      如果索引内容唯一,则为 0;如果可以不唯一,则为 1。

Key_name         索引的名称。

Seq_in_index     索引中的列序号,从 1 开始。 limit 2,3

Column_name      列名称。

Collation              列以什么方式存储在索引中。在 MySQL 中,有值‘A’(升序)或 NULL(无分类)。

Cardinality         索引中唯一值数目的估计值。

Sub_part               如果列只是被部分地编入索引,则为被编入索引的字符的数目(zhangsan 如果整列被编入索引,则为 NULL。

Packed           指示关键字如何被压缩。如果没有被压缩,则为 NULL。

Null             如果列含有 NULL,则含有 YES。如果没有,则该列含有 NO。

Index_type         用过的索引方法(BTREE, FULLTEXT, HASH, RTREE)

Comment          备注




七、删除索引

1、直接删除索引

DROP INDEX 索引名 ON 表名;

drop index suoyin_index on lcdb8;

desc lcdb8;



2、修改表方式删除索引

ALTER TABLE 表名 DROP INDEX 索引名;

alter table lcdb8 drop index suoyin_index;

3. 删除主键索引

ALTER TABLE 表名 DROP PRIMARY KEY;

alter table lcdb1 drop primary key;



用户头像

Java快了!

关注

还未添加个人签名 2022.09.03 加入

还未添加个人简介

评论

发布
暂无评论
MySQL数据库之索引_:MySQL 数据库_Java快了!_InfoQ写作社区