第08章 索引的创建与设计原则【2.索引及调优篇】【MySQL高级】1

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群版 2核4GB 100GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用版 2核4GB 50GB
简介: 第08章 索引的创建与设计原则【2.索引及调优篇】【MySQL高级】1

前言


2022/8/2 19:42


暑假学习ing


推荐

【MySQL数据库教程天花板,mysql安装到mysql高级,强!硬!-哔哩哔哩】

尚硅谷MySQL学习笔记

MySQL笔记:第08章_索引的创建与设计原则

第08章 索引的创建与设计原则

1. 索引的声明与使用

1.1 索引的分类

MySQL的索引包括普通索引、唯一性索引、全文索引、单列索引、多列索引和空间索引等。

  • 功能逻辑上说,索引主要有4种,分别是普通索引、唯一索引、主键索引、全文索引
  • 按照物理实现方式,索引可以分为2种:聚簇索引和非聚簇索引
  • 按照作用字段个数进行划分,分成单列索引和联合索引
    1.普通索引
    在创建普通索引时,不附加任何限制条件,只是用于提高查询效率。这类索引可以创建在任何数据类型中,其值是否唯一和非空,要由字段本身的完整性约束条件决定。建立索引以后,可以通过索引进行查询。例如,在表student的字段name上建立一个普通索引,查询记录时就可以根据该索引进行查询。
    2.唯一性索引

使用UNIQUE参数可以设置索引为唯一性索引,在创建唯一性索引时,限制该索引的值必须是唯一的,但允许有空值。在一张数据表里可以有多个唯一索引。
例如,在表student的字段email中创建唯一性索引,那么字段email的值就必须是唯一的。通过唯一性索引,可以更快速地确定某条记录。
3.主键索引

主键索引就是一种特殊的唯一性索引,在唯一索引的基础上增加了不为空的约束,也就是NOT NULL+UNIQUE,一张表里最多只有一个主键索引。
Why?这是由主键索引的物理实现方式决定的,因为数据存储在文件中只能按照一种顺序进行存储
4.单列索引

在表中的单个字段上创建索引。单列索引只根据该字段进行索引。单列索引可以是普通索引,也可以是唯一性索引,还可以是全文索引。只要保证该索引只对应一个字段即可。一个表可以有多个单列索引。
5.多列(组合、联合)索引
多列索引是在表的多个字段组合上创建一个索引。该索引指向创建时对应的多个字段,可以通过这几个字段进行查询,但是只有查询条件中使用了这些字段中的第一个字段时才会被使用。例如,在表中的字段id、name和gender上建立一个多列索引idx_id_name_pender ,只有在查询条件中使用了字段id时该索引才会被使用。使用组合索引时遵循 最左前缀集合。

6.全文索引
全文索引(也称全文检索〉是目前搜索引擎使用的一种关键技术。它能够利用【分词技术】等多种算法智能分析出文本文字中关键词的频率和重要性,然后按照一定的算法规则智能地筛选出我们想要的搜索结果。全文索引非常适合大型数据集,对于小的数据集,它的用处比较小。
使用参数FULLTEXT可以设置索引为全文索引。在定义索引的列上支持值的全文查找,允许在这些索引列中插入重复值和空值。全文索引只能创建在CHARVARCHARTEXT类型及其系列类型的字段上,查询数据量较大的字符串类型的字段时,使用全文索引可以提高查询速度。例如,表student的字段informationTEXT类型,该字段包含了很多文字信息。在字段information上建立全文索引后,可以提高查询字段information的速度
全文索引典型的有两种类型:自然语言的全文索引和布尔全文索引。

  • 自然语言搜索引擎将计算每一个文档对象和查询的相关度。这里,相关度是基于匹配的关键词的个数,以及关键词在文档中出现的次数。在整个索引中出现次数越少的词语,匹配时的相关度就越高。相反,非常常见的单词将不会被搜索,如果一个词语在超过50%的记录中都出现了,那么自然语言的搜索将不会搜索这类词语
    MySQL数据库从3.23.23版开始支持全文索引,但MySQL5.6.4以前只有Myisam支持,5.6.4版本以后innodb才支持,但是官方版本不支持中文分词,需要第三方分词插件。在5.7.6版本,MySQL内置了ngram全文解析器,用来支持亚洲语种的分词。测试或使用全文索引时,要先看一下自己的MySQL版本、存储引擎和数据类型是否支持全文索引

7.补充:空间索引
使用参数SPATIAL可以设置索引为空间索引。空间索引只能建立在空间数据类型上,这样可以提高系统获取空间数据的效率。MySQL中的空间数据类型包括GEONETRY、POINT、LINESTRING和POLYGON等。目前只有MyISAM存储引擎支持空间检索,而且索引的字段不能为空值。对于初学者来说,这类索引很少会用到。

小结:不同的存储引擎支持的索引类型也不一样

lnnoDB: 支持B-tree、Full-text等索引,不支持Hash索引

MylSAM: 支持 B-tree、Full-text等索引,不支持Hash索引
Memory : 支持B-tree、Hash 等索引,不支持Full-tex索引

NDB : 支持 Hash索引,不支持 B-tree、 Full-text等索引

Archive : 不支持B-tree、Hash、Full-text等索引

1.2创建索引

MySQL支持多种方法在单个或多个列上创建索引:在创建表的定义语句CREATE TABLE中指定索引列,使用ALTER TABLE语句在存在的表上创建索引,或者使用CREATE INDEX语句在已存在的表上添加索引。

1.创建表的时候创建索引

使用CREATE TABLE创建表时,除了可以定义列的数据类型外,还可以定义主键约束、外键约束或者唯一性约束,而不论创建哪种约束。在定义约束的同时相当于在指定列上创建了一个索引。

举例:

CREATE TABLE dept(
dept_id INT PRIMARY KEY AUTO_INCREMENT,
dept_name VARCHAR(20)
);
CREATE TABLE emp(
emp_id INT PRIMARY KEY AUTO_INCREMENT,
emp_name VARCHAR(20) UNIQUE,
dept_id INT,
CONSTRAINT emp_dept_id_fk FOREIGN KEY(dept_id) REFERENCES dept(dept_id)
);

但是,如果显式创建表时创建索引的话,基本语法格式如下:

CREATE TABLE table_name [col_name data_type]
[UNIQUE | FULLTEXT | SPATIAL] [INDEX | KEY] [index_name] (col_name [length]) [ASC |DESC]

UNIQUE 、 FULLTEXT 和 SPATIAL 为可选参数,分别表示唯一索引、全文索引和空间索引;

INDEX 与 KEY 为同义词,两者的作用相同,用来指定创建索引;

index_name 指定索引的名称,为可选参数,如果不指定,那么MySQL默认col_name为索引名;

col_name 为需要创建索引的字段列,该列必须从数据表中定义的多个列中选择;

length 为可选参数,表示索引的长度,只有字符串类型的字段才能指定索引长度;

ASC 或 DESC 指定升序或者降序的索引值存储。

1.创建普通索引

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

CREATE TABLE book(
  book_id INT ,
  book_name VARCHAR(100),
  authors VARCHAR(100),
  info VARCHAR(100) ,
  comment VARCHAR(100),
  year_publication YEAR,
  INDEX(year_publication)
);

测试

CREATE TABLE book(
  book_id INT ,
  book_name VARCHAR(100),
  authors VARCHAR(100),
  info VARCHAR(100) ,
  comment VARCHAR(100),
  year_publication YEAR,
  # 声明索引
  INDEX idx_bname(book_name )
);

图形化界面查看,或命令行输出


2. 创建唯一索引

举例:

CREATE TABLE test1(
  id INT NOT NULL,
  name varchar(30) NOT NULL,
  UNIQUE INDEX uk_idx_id(id)
);

测试

CREATE TABLE book1(
  book_id INT ,
  book_name VARCHAR(100),
  AUTHORS VARCHAR(100),
  info VARCHAR(100) ,
  COMMENT VARCHAR(100),
  year_publication YEAR,
  # 声明索引
  UNIQUE INDEX uk_idx_cmt(COMMENT)
);

该语句执行完毕之后,使用SHOW CREATE TABLE查看表结构:

SHOW INDEX FROM book1 \G

INSERT INTO book1(book_id,book_name,COMMENT)
VALUES(1,'Mysql高级','适合有数据库开发经验的人员学习');
SELECT * FROM book1;


声明有唯一索引的字段,在添加数据时,要保证唯一性,但是可以添加null

INSERT INTO book1(book_id,book_name,COMMENT)
VALUES(2,'Mysql高级',NULL);

3.主键索引

设定为主键后数据库会自动建立索引,innodb为聚簇索引,语法:

随表一起建索引:

CREATE TABLE student (
id INT(10) UNSIGNED AUTO_INCREMENT ,
student_no VARCHAR(200),
student_name VARCHAR(200),
PRIMARY KEY(id)
);

删除主键索引:

ALTER TABLE student
drop PRIMARY KEY ;

测试

#③ 主键索引
#通过定义主键约束的方式定义主键索引
CREATE TABLE book2(
  book_id INT PRIMARY KEY,
  book_name VARCHAR(100),
  AUTHORS VARCHAR(100),
  info VARCHAR(100) ,
  COMMENT VARCHAR(100),
  year_publication YEAR
);
SHOW INDEX FROM book2;

删除主键索引:

#通过删除主键约束的方式删除主键索引
#不能有auto_increment
ALTER TABLE book2
DROP PRIMARY KEY;

修改主键索引:必须先删除掉(drop)原索引,再新建(add)索引

4.创建单列索引

举例:

CREATE TABLE test2(
  id INT NOT NULL,
  name CHAR(50) NULL,
  INDEX single_idx_name(name(20))
);

该语句执行完毕之后,使用SHOW CREATE TABLE查看表结构:

SHOW INDEX FROM test2 \G

测试

# ④ 创建单列索引
CREATE TABLE book3(
  book_id INT ,
  book_name VARCHAR(100),
  AUTHORS VARCHAR(100),
  info VARCHAR(100) ,
  COMMENT VARCHAR(100),
  year_publication YEAR,
  # 声明索引
  UNIQUE INDEX idx_bname(book_name)
);
SHOW INDEX FROM book3;

5. 创建组合索引

举例:创建表test3,在表中的id、name和age字段上建立组合索引,SQL语句如下:

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)
);

测试

# ⑤ 创建联合索引
CREATE TABLE book4(
  book_id INT ,
  book_name VARCHAR(100),
  AUTHORS VARCHAR(100),
  info VARCHAR(100) ,
  COMMENT VARCHAR(100),
  year_publication YEAR,
  # 声明索引
  INDEX mul_bid_bname_info(book_id,book_name,info)
);
SHOW INDEX FROM book4;




6. 创建全文索引

FULLTEXT全文索引可以用于全文搜索,并且只为CHARVARCHARTEXT列创建索引。索引总是对整个列进行,不支持局部(前缀)索引。

举例1:创建表test4,在表中的info字段上建立全文索引,SQL语句如下

CREATE TABLE test4(
  id INT NOT NULL,
  NAME CHAR(30) NOT NULL,
  age INT NOT NULL,
  info VARCHAR(255),
  FULLTEXT INDEX futxt_idx_info(info(50))
) ENGINE=MYISAM;
SHOW INDEX FROM test4;


在MySQL5.7及之后版本中可以不指定最后的ENGINE了,因为在此版本中InnoDB支持全文索引

举例2:

创建了一个给title和body字段添加全文索引的表。

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

举例3:

CREATE TABLE `papers` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(200) DEFAULT NULL,
  `content` text,
  PRIMARY KEY (`id`),
  FULLTEXT KEY `title` (`title`,`content`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

不同于like方式的的查询:

SELECT * FROM papers WHERE content LIKE '%查询字符串%';

全文索引用match+against方式查询:

SELECT * FROM papers WHERE MATCH(title,content) AGAINST ('查询字符串');

明显提高效率。

注意点

  1. 使用全文索引前,搞清楚版本支持情况;
  2. 全文索引比 like + % 快 N 倍,但是可能存在精度问题;
  3. 如果需要全文索引的是大量数据,建议先添加数据,再创建索引。

7. 创建空间索引

空间索引创建中,要求空间类型的字段必须为 非空

举例:创建表test5,在空间类型为GEOMETRY的字段上创建空间索引,SQL语句如下:

CREATE TABLE test5(
  geo GEOMETRY NOT NULL,
  SPATIAL INDEX spa_idx_geo(geo)
) ENGINE=MyISAM;

该语句执行完毕之后,使用SHoW CREATE TABLE查看表结构:

SHOW INDEX FROM test5 \G

可以看到,test5表的geo字段上创建了名称为spa_idx_geo的空间索引。注意创建时指定空间类型字段值的非空约束,并且表的存储引擎为MylSAM。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
11天前
|
关系型数据库 MySQL Java
面试官:说说MySQL调优?
面试官:说说MySQL调优?
44 5
面试官:说说MySQL调优?
|
3天前
|
SQL 存储 关系型数据库
mysql加索引真的会锁表吗?揭秘背后的技术细节与规避策略
【8月更文挑战第16天】在数据库管理中,添加索引能大幅提升查询效率。MySQL执行此操作时的锁定行为常引起关注。文章详细解析MySQL中索引添加时的锁定机制及其原理。不同存储引擎及SQL语句影响锁定策略:MyISAM需全表锁定;InnoDB提供更灵活选项,如使用`ALTER TABLE... LOCK=NONE`可在加索引时允许读写访问,尽管可能延长索引构建时间。自MySQL 5.6起,在线DDL技术可进一步减少锁定时间,通过`ALGORITHM=INPLACE`和`LOCK=NONE`实现近乎无锁的表结构变更。合理配置这些选项有助于最小化对业务的影响并保持数据库高效运行。
12 4
|
3天前
|
SQL JavaScript 关系型数据库
Mysql索引不当引发死锁问题
本文通过真实案例解析了MySQL在高并发环境下出现死锁的问题。数据库表`t_award`包含多个索引,但在执行特定SQL语句时遭遇索引失效,导致更新操作变慢并引发死锁。分析发现,联合索引`(pool_id, identifier, status, is_redeemed)`因`identifier`允许为空值而导致索引部分失效。此外,`pool_id`上的普通索引产生的间隙锁在高并发下加剧了死锁风险。为解决此问题,文中提出了调整索引顺序至`(pool_id, status, is_redeemed, identifier)`等方案来优化索引使用,进而减轻死锁现象。
|
6天前
|
缓存 NoSQL Redis
一天五道Java面试题----第九天(简述MySQL中索引类型对数据库的性能的影响--------->缓存雪崩、缓存穿透、缓存击穿)
这篇文章是关于Java面试中可能会遇到的五个问题,包括MySQL索引类型及其对数据库性能的影响、Redis的RDB和AOF持久化机制、Redis的过期键删除策略、Redis的单线程模型为何高效,以及缓存雪崩、缓存穿透和缓存击穿的概念及其解决方案。
|
13天前
|
缓存 关系型数据库 MySQL
MySQL调优秘籍曝光!从索引到事务,全方位解锁高可用秘诀,让你的数据库性能飞起来!
【8月更文挑战第6天】MySQL是顶级关系型数据库之一,其性能直接影响应用的高可用性与用户体验。本文聚焦MySQL的高性能调优,从索引设计到事务管理,逐一解析。介绍如何构建高效索引,如联合索引`CREATE INDEX idx_order_customer ON orders(order_id, customer_id);`,以及索引覆盖查询等技术。
39 0
|
6天前
|
存储 关系型数据库 MySQL
MySQL——数据库备份上传到阿里云OSS存储
MySQL——数据库备份上传到阿里云OSS存储
20 0
|
9天前
|
SQL 存储 关系型数据库
"MySQL增列必锁表?揭秘InnoDB在线DDL,让你的数据库操作飞一般,性能无忧!"
【8月更文挑战第11天】在数据库领域,MySQL凭借其稳定高效的表现深受开发者喜爱。对于是否会在给数据表添加列时锁表的问题,MySQL的行为受版本、存储引擎等因素影响。从5.6版起,InnoDB支持在线DDL,可在改动表结构时保持表的可访问性,避免长时间锁表。而MyISAM等则需锁表完成操作。例如,在使用InnoDB的表上运行`ALTER TABLE users ADD COLUMN email VARCHAR(255);`时,通常不会完全锁表。虽然在线DDL提高了灵活性,但复杂操作或大表变更仍可能暂时影响性能。因此,进行结构变更前应评估其影响并择机执行。
31 6
|
8天前
|
Oracle 关系型数据库 MySQL
Mysql和Oracle数据库死锁查看以及解决
【8月更文挑战第11天】本文介绍了解决MySQL与Oracle数据库死锁的方法。MySQL可通过`SHOW ENGINE INNODB STATUS`查看死锁详情,并自动回滚一个事务解除死锁;也可手动KILL事务。Oracle则通过查询V$LOCK与V$SESSION视图定位死锁,并用`ALTER SYSTEM KILL SESSION`命令终止相关会话。预防措施包括遵循ACID原则、优化索引及拆分大型事务。
|
9天前
|
固态存储 关系型数据库 MySQL
"惊!20亿数据秒速入MySQL,揭秘数据库极速插入的黑科技,你不可不知的绝密技巧!"
【8月更文挑战第11天】面对20亿级数据量,高效插入MySQL成为挑战。本文探讨优化策略:合理设计数据库减少不必要的字段和索引;使用批量插入减少网络往返;优化硬件如SSD和内存及调整MySQL配置;并行处理加速插入;附Python示例代码实现分批导入。这些方法将有效提升大规模数据处理能力。
25 2
|
10天前
|
存储 关系型数据库 MySQL
"Linux环境下MySQL数据库名及表名大小写敏感性设置详解:从配置到影响,确保数据库操作的准确与高效"
【8月更文挑战第9天】在Linux环境中,MySQL数据库名及表名的大小写敏感性是一项重要配置。默认情况下,MySQL在Linux上区分大小写,但这可通过配置文件 `/etc/my.cnf` 中的 `lower_case_table_names` 参数调整。该参数设为0时,名称存储时保持原样,查询时不区分大小写;设为1则全部转换为小写。通过编辑配置文件并重启MySQL服务,可根据需求灵活控制名称的大小写敏感性,确保数据一致性和应用兼容性。
28 3