• MySQL数据库之索引


    目录

    一.索引概述

    二.索引作用的优缺点

    1.优点

    2.缺点

    三.创建索引的原则依据

    四.适用索引的场景

    五.索引的分类和创建

    1.普通索引

    2.唯一索引

    3.修改表方式创建

    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;

  • 相关阅读:
    Docker Compose
    Python实现猎人猎物优化算法(HPO)优化循环神经网络分类模型(LSTM分类算法)项目实战
    【代码随想录】算法训练计划01
    UE5物体旋转(蓝图版)
    关于 Python 的 import
    情绪识别公开数据集汇总心电相关and申请方法详细描述 呕心沥血之作 全网唯一
    Lego-Laom算法深度解析
    了解ixgbe网卡驱动— 驱动注册(纯代码分享)
    Python基础笔记持续记录
    【web-攻击用户】(9.7.1)本地隐私攻击:持久性cookie、缓存Web内容、浏览历史记录、Flash本地共享对象……
  • 原文地址:https://blog.csdn.net/a_b_e_l_/article/details/126840649