玩转Mysql 七 (索引的创建与设计原则)

一路走来,所有遇到的人,帮助过我的、伤害过我的都是朋友,没有一个是敌人。

一、索引的创建与使用

1、索引的分类

MySQL的索引包括普通索引、唯一性索引、全文索引、单列索引、多列索引和空间索引等。
(1)从 功能逻辑 上说,索引主要有 4 种,分别是普通索引、唯一索引、主键索引、全文索引。
(2)按照 物理实现方式 ,索引可以分为 2 种:聚簇索引和非聚簇索引。
(3)按照 作用字段个数 进行划分,分成单列索引和联合索引。

2、mysql索引的拓扑图

3、mysql索引概述

索引是排好序的数据结构,能够就少I/O次数。
MySQL-INNODB引擎使用B+树数据结构作为索引。
B树和B+树最大的区别是将数据存储到了叶子节点,并且叶子节点之间用指针相连。

  • 主键索引PRIMARY KEY:不为空、不能重复
  • 唯一索引UNIQUE:可为空,不能重复
  • 普通索引INDEX:加速查找
  • 联合索引:PRIMARY KEY(id,name):联合主键索引 UNIQUE(id,name):联合唯一索引INDEX(id,name):联合普通索引

4、创建索引的三种方式

(1)创建表时同时创建索引

CREATE TABLE users(
userid INT ,
username VARCHAR(100),
age YEAR,
email VARCHAR(100),
INDEX email_inx(email) 
);

(2)创建完表后再单独一列创建索引

CREATE INDEX name_inx ON users(username);

(3)将表的一列更改为索引

ALTER TABLE users ADD INDEX age_index(age);

4、查看表的索引

方式一:SHOW INDEX FROM users;

方式二:

SHOW CREATE TABLE users \G;

SHOW CREATE TABLE users ;

二、索引类型的优缺点

1、普通索引

普通索引是数据库中最基本的索引结构,也被称为单列索引或简单索引。它只包含一个列的值和指向该行的指针,用于加速对该列的单列查询。可以对表的任意列创建普通索引,但通常建议对经常进行查询和排序的列创建索引,例如主键列和外键列等。

普通索引的原理是将所需要查询的列作为索引列,按照索引列的值建立索引。当查询该列时,数据库系统会先在索引结构中进行查找,然后根据索引中的指针到数据表中找到对应的行。由于普通索引只包含一个列的值和指向该行的指针,因此查询时需要在数据表中找到其他所需的列的值。

普通索引的优点包括:

(1)可以加速单列查询的速度,特别是对于大型数据表和频繁的查询操作。

(2)可以提高数据的访问效率,从而加快数据的处理速度。

普通索引的缺点包括:

(1)当需要查询的列不在索引列中时,需要进行额外的查找操作,从而降低查询效率。

(2)创建普通索引需要占用额外的磁盘空间和内存空间,可能会对写入操作的性能产生一定的影响。

普通索引的使用场景包括

(1)经常进行查询和排序操作的列。

(2)需要经常进行连接操作的表的外键列。

(3)数据表中需要保证唯一性的列,如主键列等。

普通索引是数据库中最基本的索引结构,用于加速对单列查询的速度,提高数据的访问效率。在创建普通索引时需要根据具体的业务需求进行选择,避免对写入操作的性能产生过大的影响。

示例:创建普通索引

在book表中的year_publication字段上建立普通索引,SQL语句如下:
(1)在创建表中创建索引

(2)查看索引信息

方式一 :SHOW INDEX FROM users;

方式二:

(3)删除索引

方式一:ALTER  TABLE  表名称  DROP  索引名称;

ALTER TABLE users DROP INDEX   email_inx;

方式二:DROP  INDEX  索引名称  ON  表名称;

DROP INDEX name_inx ON users; 

2、唯一索引

唯一索引是一种限制数据库表中列值唯一性的索引,用于保证在指定列上没有重复的数据。与普通索引不同,唯一索引在索引列中的每个值都是唯一的,且不允许插入重复值,包括 NULL 值

唯一索引的原理与普通索引类似,只是对于唯一索引而言,如果插入或更新操作的列值已经存在,数据库系统会抛出一个唯一性冲突的错误。唯一索引可以用于加速唯一性约束条件的验证(创建唯一性索引会默认创建唯一性约束,反之亦然),从而提高数据的访问效率。

唯一索引的优点包括:

(1)可以保证数据表中的列值唯一性,避免重复数据的插入。

(2)可以提高数据的访问效率,加速唯一性约束条件的验证。

唯一索引的缺点包括:

(1)创建唯一索引需要占用额外的磁盘空间和内存空间,可能会对写入操作的性能产生

        一定的影响。

(2)如果需要对多个列进行唯一性约束,需要创建多个唯一索引,会占用更多的磁盘空间和

         内存空间。

唯一索引的使用场景包括:

(1)需要对数据表中的某一列或多个列进行唯一性约束的情况。

(2)经常进行查询和排序操作的列需要保证唯一性。

唯一索引是一种用于限制数据库表中列值唯一性的索引,可以保证数据表中的列值唯一性,提高数据的访问效率。在创建唯一索引时需要根据具体的业务需求进行选择,避免对写入操作的性能产生过大的影响。

创建唯一索引的两种方式:

方式1:建立表时创建

CREATE TABLE users2(
userid INT    ,
username VARCHAR(100),
age YEAR,
email VARCHAR(100),
UNIQUE INDEX  use_idx_id(userid)
);

方式2:建立表后再指定的列上创建

ALTER TABLE users2 ADD UNIQUE use_idx_id(userid);

(3)普通索引 VS 唯一索引的展示对比

(4)删除唯一索引

方式一:DROP INDEX index_name on  table_nam;

DROP INDEX use_idx_id on users2;

方式二:ALTER TABLE table_nam DROP INDEX use_idx_id;

ALTER TABLE users2 DROP INDEX use_idx_id;

测试唯一索引:插入重复的值

SELECT * FROM users2;

INSERT INTO users2(userid,username,age,email)  VALUE ('1','jack','18','tom.126.com');

测试唯一索引:插入NULL 值

INSERT INTO users2(userid,username,age,email) 
VALUE(null,'jack','18','jack.126.com');

唯一索引可以插入NULL值,建表时需要注意

3、主键索引

主键索引是一种基于数据库表中主键的索引技术,主要用于加速对数据库表中某个记录的查找和访问。主键是一种唯一标识数据库表中每个记录的字段或一组字段,每个记录都应该具有不同的主键值,主键是一种特殊的唯一索引,必须指定为"PRIMARY KEY"。 一个表只能有一个主键,不允许有空值。添加主键将自动创建主键索引。

主键索引通常使用B+树等数据结构进行实现,以便能够快速地查找和定位某个记录。

主键索引的特点包括:

(1)主键索引是一种唯一索引,要求每个记录的主键值都是唯一的。

(2)主键索引通常是表中的主键字段上创建的索引,可以加快对该字段的查找和访问速度。

(3)主键索引可以用于加速数据库表的连接操作和数据的排序操作。

主键索引的优点包括:

(1)提高了对数据库表中某个记录的查找和访问速度,降低了访问数据库表的成本。

(2)由于主键值是唯一的,可以保证每个记录都能被唯一地标识和访问。

(3)可以用于加速数据库表的连接操作和数据的排序操作,提高了查询和分析数据的效率。

主键索引的缺点包括:

(1)主键索引只适用于基于主键的查询,对于其他类型的查询可能会不够高效。

(2)在插入新记录或更新主键值时,需要重新维护主键索引,可能会对数据库性能产生影响。

(3)如果主键值不够唯一或者数据量较大,主键索引可能会占用较多的磁盘空间和内存空间。

主键索引是一种基于数据库表中主键的索引技术,可以提高对数据库表中某个记录的查找和访问速度,用于加速数据库表的连接操作和数据的排序操作。在使用主键索引时需要考虑到其对于其他类型的查询可能不够高效,以及在插入新记录或更新主键值时需要重新维护主键索引的成本。MySQL 主键索引还是聚簇索引。

创建主键索引的方式

方式一:建表时同时创建

CREATE TABLE users3(
userid INT(10) PRIMARY KEY  ,
username VARCHAR(100),
age YEAR,
email VARCHAR(100)
);
方式二:建表后创建

ALTER TABLE users3 ADD CONSTRAINT  PRIMARY KEY (userid);

   删除主键索引

ALTER TABLE table_name DROP PRIMARY KEY;

ALTER TABLE users3 DROP PRIMARY KEY;

测试主键索引

  

测试插入重复值

INSERT INTO users3(userid,username,city,email) 
VALUE('1','jack','hb','tom.126.com');

测试插入空值

INSERT INTO users3(userid,username,city,email) 
VALUE(NULL,'jack','hb','tom.126.com');

3、复合(联合)索引

复合索引是一种将多个列组合在一起来创建的索引,用于优化查询中涉及到多个列的查询效率。相对于单列索引,复合索引可以更有效地支持多列的查询,提高查询效率。

在创建复合索引时,可以选择多个列,并按照顺序依次排列。这样可以使得查询更加高效,因为复合索引的叶子节点存储的是多列的值,可以直接满足多列查询的需求,避免了查询时多次进行索引扫描的开销。

例如,对于一个包含姓名和年龄的表,可以创建一个复合索引,将这三列按照顺序依次排列。这样,当需要查询姓名、性别和年龄都满足一定条件的记录时,可以直接使用复合索引来完成查询,避免了多次索引扫描的开销,从而提高了查询效率。

复合索引的优点包括

(1)可以提高多列查询的效率,避免多次索引扫描的开销。

(2)可以减小索引的存储空间,适用于需要对多个列进行查询的表。

复合索引的缺点包括

(1)复合索引的维护成本比单列索引高,因为需要对多个列进行维护。

(2)对于一些单列查询,复合索引可能并不适用,因为需要扫描复合索引的叶子节点,而单列索引可以直接定位到需要的记录。

复合索引的使用场景包括:

(1)需要对多列进行查询的表,例如包含姓名和年龄等多个列的表。

(2)查询操作较多,更新操作较少的表。

创建联合索引方式

方式一:创建表时创建

CREATE TABLE test3(
id INT(11) NOT NULL,
name CHAR(30) NOT NULL,
age INT(11) NOT NULL,
info VARCHAR(255),
INDEX multi_idx(id,name,age)
);

方式二:创建表后增加

ALTER TABLE test3 ADD INDEX multi_idx(id,name,age);

删除联合索引

DROP INDEX multi_idx ON test3;

4、全文索引

全文索引是一种基于文本内容的索引技术,可以快速地检索出包含指定关键词或短语的文档或记录,只支持VARCHAR/CHAR类型数据。相比于传统的索引技术,全文索引更加适用于文本数据的搜索和查询。

全文索引通常使用倒排索引(Inverted Index)的数据结构,将每个单词或短语出现的位置作为索引项,以便进行快速的查找和匹配。倒排索引可以理解为是一张单词词表,每个单词都指向包含该单词的文档或记录的位置。通过倒排索引,可以快速地找到包含指定单词的文档或记录,以及它们出现的位置。

全文索引的优点包括:

(1)可以对文本数据进行高效的搜索和查询,提高数据的访问效率。

(2)可以支持模糊搜索和短语搜索等功能,增强搜索的灵活性和准确性。

全文索引的缺点包括:

(1)创建全文索引需要占用大量的磁盘空间和内存空间,可能会对系统的性能产生影响。

(2)全文索引的更新和维护成本较高,需要花费较多的时间和资源。

全文索引的使用场景包括:

(1)需要对大量文本数据进行搜索和查询的情况,如新闻、博客、社交媒体等应用。

(2)需要支持模糊搜索和短语搜索等高级搜索功能的情况。

全文索引是一种基于文本内容的索引技术,可以高效地对文本数据进行搜索和查询,支持模糊搜索和短语搜索等高级搜索功能。在使用全文索引时需要考虑到其占用的磁盘空间和内存空间,以及更新和维护的成本。

创建全文索引

CREATE TABLE test5 (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
title VARCHAR (200),
body TEXT,
FULLTEXT INDEX  full_idx (title, body)
) ENGINE = INNODB ;

SHOW INDEX FROM test5;

注意: 删除表中的列时,如果要删除的列为索引的组成部分,则该列也会从索引中删除。如果组成索引的所有列都被删除,则整个索引将被删除。
 

三、MySQL8.0索引新特性

1、支持降序索引

 降序索引:实际上升序索引和降序索引是不同的排序方式而已,Mysql8中正在实现了降序索引后,我们在创建索引时更加灵活,可以根据业务需要的排序规则来创建合适的索引,这样能使你的查询更快,而且现在只有Innodb存储引擎支持降序索引。MySQL 8.0引入的降序索引,最重要的作用是,解决了多列排序可能无法使用索引的问题,从而可以覆盖更多的应用场景。

2、测试降序索引的查询效率

(1)使用mysql 5 和 mysql 8 建立相同的表,插入相同的数据,进行测试

    CREATE TABLE ts1(a int,b int,index idx_a_b(a,b desc));
(2)插入相同的数据

DELIMITER //
CREATE PROCEDURE ts_insert()
BEGIN
DECLARE i INT DEFAULT 1;
WHILE i < 800
DO
insert into ts1 select rand()*80000,rand()*80000;
SET i = i + 1;
END WHILE;
commit;
END //
DELIMITER ;

调用ts_insert,查看表中数据
CALL ts_insert();

3、mysql 5 测试查询,查看执行计划

从结果可以看出,执行计划中扫描数为799,而且使用了Using filesort, Using filesort是MySQL中一种速度比较慢的外部排序,能避免是最好的。多数情况下,管理员可以通过优化索引来尽量避免出现Using filesort,从而提高数据库执行速度。
4、mysql 8 测试查询,查看执行计划

在MySQL 8.0版本中查看数据表ts1的执行计划。从结果可以看出,执行计划中扫描数为5,而且没有使用Using filesort。降序索引只对查询中特定的排序顺序有效,如果使用不当,反而查询效率更低。例如,上述查询排序条件改为order by a desc, b desc,MySQL 5.7的执行计划要明显好于MySQL 8.0。
示例演示:

EXPLAIN SELECT * FROM ts1 ORDER BY a DESC,b DESC LIMIT 5;

MySQL 8演示

从结果可以看出,执行计划中扫描数为799,而且使用了Using filesort

mysql 5 展示

从结果可以看出,执行计划中扫描数为799,没有使用Using filesort

从结果可以看出,修改后MySQL 5.7的执行计划要明显好于MySQL 8.0。
 

四、隐藏索引(可以理解为将索引置为失效状态,查看SQL的执行效率

1、MySQL 8 新特性 隐藏索引

在MySQL 5.7版本及之前,只能通过显式的方式删除索引。此时,如果发现删除索引后出现错误,又只能通过显式创建索引的方式将删除的索引创建回来。如果数据表中的数据量非常大,或者数据表本身比较大,这种操作就会消耗系统过多的资源,操作成本非常高。
从MySQL 8.x开始支持 隐藏索引(invisible indexes) ,只需要将待删除的索引设置为隐藏索引,使查询优化器不再使用这个索引(即使使用force index(强制使用索引),优化器也不会使用该索引),确认将索引设置为隐藏索引后系统不受任何响应,就可以彻底删除索引。 这种通过先将索引设置为隐藏索引,再删除索引的方式就是软删除 。

2、隐藏索引创建的方式

方式一:创建表时一起创建

CREATE TABLE test6(
id INT(11) NOT NULL,
name CHAR(30) NOT NULL,
age INT(11) NOT NULL,
info VARCHAR(255),
INDEX name_idx(NAME) INVISIBLE
);

SHOW INDEX FROM test6

方式二:创建完表的增加

将索引更改为可现性/隐藏性

ALTER TABLE test6 ALTER INDEX  age_idx VISIBLE; (INVISIBLE)
SHOW INDEX FROM test6;

注意 当索引被隐藏时,它的内容仍然是和正常索引一样实时更新的。如果一个索引需要长期被隐
藏,那么可以将其删除,因为索引的存在会影响插入、更新和删除的性能。
 

3、使隐藏索引对查询优化器可见(了解)
在MySQL 8.x版本中,为索引提供了一种新的测试方式,可以通过查询优化器的一个开关
(use_invisible_indexes)来打开某个设置,使隐藏索引对查询优化器可见。如use_invisible_indexes设置为off(默认),优化器会忽略隐藏索引。如果设置为on,即使隐藏索引不可见,优化器在生成执行计
划时仍会考虑使用隐藏索引。

(1)在MySQL命令行执行如下命令查看查询优化器的开关设置。
         在输出的结果信息中找到如下属性配置。
         此属性配置值为off,说明隐藏索引默认对查询优化器不可见。
(2)使隐藏索引对查询优化器可见,需要在MySQL命令行执行如下命令:SQL语句执行成功,再次查看查询优化器的开关设置。此时,在输出结果中可以看到如下属性配置。
use_invisible_indexes属性的值为on,说明此时隐藏索引对查询优化器可见。
ALTER TABLE tablename
ADD INDEX indexname (propname [(length)]) INVISIBLE;
ALTER TABLE tablename ALTER INDEX index_name INVISIBLE; #切换成隐藏索引
ALTER TABLE tablename ALTER INDEX index_name VISIBLE; #切换成非隐藏索引
mysql> select @@optimizer_switch \G
use_invisible_indexes=off
mysql> set session optimizer_switch="use_invisible_indexes=on";
Query OK, 0 rows affected (0.00 sec)

mysql> select @@optimizer_switch \G
*************************** 1. row ***************************
@@optimizer_switch:
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_
intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,mrr=on,mrr_co
st_based=on,block_nested_loop=on,batched_key_access=off,materialization=on,semijoin=on
,loosescan=on,firstmatch=on,duplicateweedout=on,subquery_materialization_cost_based=on
,use_index_extensions=on,condition_fanout_filter=on,derived_merge=on,use_invisible_ind
exes=on,skip_scan=on,hash_join=on
1 row in set (0.00 sec)
use_invisible_indexes=on
(3)使用EXPLAIN查看以字段invisible_column作为查询条件时的索引使用情况。查询优化器会使用隐藏索引来查询数据。
(4)如果需要使隐藏索引对查询优化器不可见,则只需要执行如下命令即可。
再次查看查询优化器的开关设置。
此时,use_invisible_indexes属性的值已经被设置为“off”。

四、索引设计的原则
大佬博文推荐
https://www.cnblogs.com/sha-Pao-Zi/p/16314941.html

MySQL高级篇——索引的创建与设计原则

相关推荐

  1. 索引设计原则MySQL

    2024-01-16 15:00:05       28 阅读
  2. MySQL索引设计遵循一系列原则

    2024-01-16 15:00:05       13 阅读
  3. MySQL篇之索引创建失效

    2024-01-16 15:00:05       29 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-01-16 15:00:05       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-01-16 15:00:05       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-01-16 15:00:05       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-01-16 15:00:05       18 阅读

热门阅读

  1. MATLAB十六进制与十进制互相转换

    2024-01-16 15:00:05       36 阅读
  2. simulink之parameter

    2024-01-16 15:00:05       31 阅读
  3. Redis提供了哪几种持久化方式?

    2024-01-16 15:00:05       30 阅读
  4. uniapp一键换色

    2024-01-16 15:00:05       32 阅读
  5. UML相关问题及答案(2024)

    2024-01-16 15:00:05       32 阅读
  6. npm包管理工具

    2024-01-16 15:00:05       24 阅读