这是命令行操作MySQL数据库系列博客的第十二篇,今天这篇博客记录《表索引》如何进行操作。(普通索引、唯一索引、全文索引、多列索引、隐藏索引、删除索引和修改索引)
索引概述
-
基本概念
日常生活中,我们经常会在电话号码簿中查阅“某人”的电话号码,按姓查询或者按字母排序查询; 在字典中查阅“某个词”的读音和含义等等,以快速的找到特定记录。在这里,“姓”和“字母”都可看作是索引, 而按“姓”或者“字母”查询则是按索引查询!索引是一种特殊的数据库结构,可以用来快速查询数据库表中的特定记录,是提高数据库性能的重要方式。MySQL中,所有的数据类型都可以被索引。
通过索引,查询数据时可以不必读完记录的所有信息,而只是查询索引列,否则数据库系统将读取每条记录的所有信息进行匹配。例如,索引相当于新华字典的音序表,如果要查“过”字,如果不适用音序,就需要从字典的第一页开始翻几百页;如果提取拼音出来,构成音序表,就只需要从10多页的音序表中直接查找,这样就可以大大节省时间。因此,使用索引可以在很大程度上提高数据库的查询速度,有效地提高了数据库系统的性能。
-
索引类型
索引包括普通索引、唯一性索引、全文索引、单列索引、多列索引和空间索引等。下文中将详细介绍~
-
索引存储
数据库底层索引实现主要有两种存储类型,B树(BTREE)和哈希(HASH)索引。
-
索引优点
可以提高检索数据的速度。 -
索引缺点
创建和维护索引需要耗费时间,耗费时间的数量随着数据量的增加而增加;索引需要占用物理空间,每一个索引要占一定的物理空间;增加、删除和修改数据时,要动态地维护索引,造成数据的维护速度降低了。
-
使用建议
索引可以提高查询的速度,但是会影响插入记录的速度,因为向有索引的表中插入记录时,数据库系统会按照索引进行排序,这样就降低了插入记录的速度,插入大量记录时的速度影响更加明显。这种情况下,最好的办法是先删除表中的索引,然后插入数据,插入完成后再创建索引。
创建和查看索引
创建索引是指在某个表的一列或多列上建立一个索引,以便提高对表的访问速度。
创建索引有3种方式:
- 创建表的时候创建索引
- 在已经存在的表上创建索引
- 使用ALTER TABLE语句来创建索引。
本篇博客将根据具体的索引分类详细的讲解这3种创建方法。
一、普通索引
所谓普通索引,就是在创建索引时,不附加任何限制条件(唯一、非空等限制)。该类型的索引可以创建在任何数据类型的字段上。
1. 创建表时定义索引
create table 表名(字段1 类型 , ..., 字段n 类型, INDEX [索引别名] (字段名[(长度)] [ASC | DESC]));
(括号)内是必填,[中括号]是可填可不填
索引别名:自己填的索引别名,可不填;
字段名:索引对应字段的名称,该字段必须在前面定好;
长度:可不填的参数,其指定索引的长度,必须是字符串类型才可以使用;
ASC:表示升序排列,不填则默认为升序;
DESC:表示降序排列。
关于长度,使用字符串作为索引时,不指定长度也是可以的,下面全文索引中会有例子。
例:
-
创建
create table index1(id int, name varchar(32), sex enum('男', '女', '未知'), INDEX index_no(id DESC));
定义id字段为索引,且索引别名为index_no,设置为降序排序。 -
插入与查询
2. 已存在的表上创建索引
第二种和第三种创建索引的方式包含再次。
(1). 执行create 语句
create INDEX 索引别名 ON 表名(字段名[(长度)] [ASC | DESC]);
(括号)内是必填,[中括号]是可填可不填
INDEX:用来指定字段为索引;
索引别名:自己填的索引别名,此处必须填;
NO:关键字;
表名:是指需要创建索引的表的名称,该表必须是已经存在的,如果不存在,需要先创建;
字段名:指定索引对应的字段的名称,该字段必须为前面定义好的字段;
长度:可不填,表示索引的长度,必须是字符串类型才可以使用;
ASC:表示升序排列,默认为升序;
DESC:表示降序排列。
关于长度,使用字符串作为索引时,不指定长度也是可以的,下面全文索引中会有例子。
例:
新建该表用于新增索引:
create table index2(id int, name varchar(32), sex enum('男', '女', '未知'));
追加升序排序索引 :
create INDEX id_no ON index2(id ASC);
可以通过show create table index2;
语句进行查询
(2). 执行alter table 语句
alter table 表名 ADD INDEX 索引别名(字段名[(长度)] [ASC | DESC]);
(括号)内是必填,[中括号]是可填可不填
表名:需要创建索引的表,该表必须是已经存在的,如果不存在,需要先创建;
ADD:关键字;
INDEX:用来指定字段为索引;
索引别名:自己填的索引别名,此处必须填;
字段名:指定索引对应的字段的名称,该字段必须为前面定义好的字段;
长度:可不填,表示索引的长度,必须是字符串类型才可以使用;
ASC:表示升序排列,默认为升序;
DESC:表示降序排列。
关于长度,使用字符串作为索引时,不指定长度也是可以的,下面全文索引中会有例子。
例:
新建该表用于新增索引:
create table index3(id int, name varchar(32));
追加降序排序索引 :
alter table index3 ADD INDEX index_id(id DESC);
3. 查看索引执行情况
EXPLAIN 查询语句
注意:如果需要促发索引去查询数据,必须指定查询条件。
key: 实际使用的索引。如果为NULL,则没有使用索引;
possible_keys:显示可能应用在这张表中的索引,一个或多个。查询涉及到的字段上若存在索引,则该索引 将被列出,但不一定被查询实际使用;
key_len: 表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度。此值越短越好!
二、唯一索引
所谓唯一索引,就是在创建索引时,限制索引的字段值必须是唯一的。通过该类型的索引可以比普通索引更快速地查询某条记录。
其实也是和普通索引差不多,唯一索引在创建时多写UNIQUE关键字。
1. 创建表时定义索引
create table 表名(字段1 类型, ..., 字段n 类型, UNIQUE INDEX [索引别名] (字段名[(长度)] [ASC | DESC]));
例:
create table index4(id int, name varchar(32), UNIQUE INDEX index_id(id DESC));
2. 已存在的表上创建索引
(1). 执行create 语句
create UNIQUE INDEX 索引别名 ON 表名(字段名[(长度)] [ASC | DESC]);
例:
新建该表用于新增索引:
create table index5(id int, name varchar(32));
创建索引:
create UNIQUE INDEX index_name ON index5(name(32));
(2). 执行alter table 语句
alter table 表名 ADD UNIQUE INDEX 索引别名(字段名[(长度)] [ASC | DESC]);
例:
新建该表用于新增索引:
create table index6(id int, name varchar(32));
创建索引:
alter table index6 ADD UNIQUE INDEX index_name(name(32) DESC);
三、全文索引
全文索引主要对字符串类型建立基于分词的索引,主要是基于char、varchar和text的字段上,以便能够更加快速地查询数据量较大的字符串类型的字段。
全文索引以词为基础的,MySQL默认的分词是所有非字母和数字的特殊符号都是分词符。
在默认情况下,全文索引的搜索执行方式为不区分大小写,如果全文索引所关联的字段为二进制数据类型,就以区分大小写的搜索方式执行。
通俗讲解:大家都用过百度引擎搜索东西吧,当我们输入关键字搜索时,页面会将有相同关键字的连接显示出来。这也就是全文索引的使用。
1. 创建表时定义索引
create table 表名(字段1 类型, ..., 字段n 类型 FULLTEXT INDEX [索引别名](字段名[长度]));
例:
create table index7(id int, _text varchar(128), FULLTEXT INDEX index_text(_text(128)));
插入数据:
insert into index7 values(1, '我是一名共青团员,我爱祖国');
用全文检索索引快速查询记录:
select * from 表名 where match(字段名) AGAINST('需要匹配的字符串');
select * from index7 where match(_text) AGAINST('我爱祖国');
注意,必须输入以逗号隔开的一整段才行。
否则:
但是MySQL8也支持中文分词查询;相关设置如下第四步骤。
2. 已存在的表上创建索引
(1). 执行create 语句
在MySQL中创建全文索引除了通过SQL语句FULLTEXT INDEX来实现外,还可以通过SQL语句create FULLTEXT INDEX来实现,其语法形式如下:
create FULLTEXT INDEX 索引别名 ON 表名(字段名[(长度)]);
例:
新建该表用于新增索引:
create table index8(id int, _text varchar(128));
新增索引:
create FULLTEXT INDEX index_text ON index8(_text(128));
可以通过show create table index8;
语句查看
(2). 执行alter table 语句
除了上述两种方式来创建全文索引外,在MySQL中创建全文索引还可以通过SQL语句alter来实现,其语法形式如下:
alter table 表名 ADD FULLTEXT INDEX 索引别名(字段名([长度]));
例:
新建该表用于新增索引:
create table index9(id int, _text varchar(128));
新增索引:
alter table index9 ADD FULLTEXT INDEX index_text(_text(128));
3. 使用场景
根据全文索引字段进行全文检索数据:
select * from 表名 where MATCH(字段名) AGAINST('关键字');
例:
insert into index9 values(1, '我是一名光荣的打工人,我爱打工');
select * from index9 where MATCH(_text) AGAINST('我爱打工');
只能通过以逗号隔开的语段进行查询,但是MySQL8也支持中分分词查询;相关设置如下第四步骤。
4. MySQL8 中文分词支持
配置文件my.ini(Windows 10默认路径: C:\ProgramData\MySQL\MySQL Server 8.0) 中增加如下配置项,同时重启MySQL80 服务。
[mysqld]
ngram_token_size=2
找到如下图片对应的.ini文件,打开并找到[mysqld]项,在其下面添加ngram_token_size=2 MySQL就可以支持以两个中文字符作为分词的检索了。
正确的来说是支持两个中文字符以上的中文字符进行检索
添加好后,重启MySQL服务。
设置好后,MySQL以两个以上的中文字符作为分词。
如下图:
“我是”:是一组;“是谁”:是一组;…;“地方”:是一组。
正确的来说是支持两个中文字符以上的中文字符进行检索
例:
-
创建新表时:
create table index10(id int, _text varchar(128), FULLTEXT INDEX index_text(_text) with parser ngram);
在后面加上
with parser ngram
目前博主只会在新创建表时添加设置,如果是在已有的表上添加,这个博主目前貌似还不知道怎么操作,也不知可不可以进行这样的操作。
-
插入数据,并测试:
insert into index10 values(1, '我是谁?我在那里?这是什么地方?'); select * from index10 where MATCH(_text) AGAINST('我是'); select * from index10 where MATCH(_text) AGAINST('么地方');#也支持三个以上的中文检索 select * from index10 where MATCH(_text) AGAINST('么地');
四、多列索引
多列索引,是指在创建索引时所关联的字段不是一个字段,而是多个字段,虽然可以通过所关联的字段进行查询,但是只有查询条件中使用了所关联字段中的第一个字段,多列索引才会被使用。
1. 创建表时定义索引
create table 表名(字段1 类型, 字段2 类型, ..., 字段n 类型, INDEX [索引别名](字段名1[长度] [ASC | DESC], ..., 字段名n[长度] [ASC | DESC]));
注意:和普通索引定义基本相同,不同之处就是增加了多个索引列。
例:
create table index11(id int, _text varchar(128), sex enum('男', '女'), INDEX index_id_text(id DESC, _text));
创建表以id字段和_text字段为索引
使用show create table index11;
查看表定义
插入数据并使用索引进行查询
仅根据id查询记录才会启用多列索引
2. 已存在的表上创建索引
(1). 执行create 语句
create INDEX 索引别名 ON 表名(字段名1[(长度)][ASC | DESC], ..., 字段名n[(长度)][ASC | DESC]);
例:
新建该表用于新增索引:
create table index12(id int, _text varchar(128));
新增索引:
create INDEX index_id_text ON index12(id, _text);
可以通过show create table index12;
语句查看
(2). 执行alter table 语句
除了上述两种方式来创建全文索引外,在MySQL中创建全文索引还可以通过SQL语句alter来实现,其语法形式如下:
alter table 表名 ADD INDEX 索引别名(字段名1([长度])[ASC | DESC], ..., 字段名n([长度])[ASC | DESC]);
例:
新建该表用于新增索引:
create table index13(id int, _text varchar(128));
新增索引:
alter table index13 ADD INDEX index_id_text(id DESC, _text(128));
五、隐藏索引
MySQL 8开始支持隐藏索引。隐藏索引提供了更人性化的数据库操作。
隐藏索引,顾名思义,让索引暂时不可见,不会被优化器使用。默认情况下索引是可见的。隐藏索引可以用来测试索引的性能。验证索引的必要性时不需要删除索引,可以先将索引隐藏,如果优化器性能无影响就可以真正地删除索引。
alter table 表名 ALTER INDEX 索引别名 INVISIBLE; #隐藏索引
alter table 表名 ALTER INDEX 索引别名 VISIBLE; #取消隐藏
例:
我们以表index13为例,先看看index13的索引:
show create table index13;
隐藏索引:
alter table index13 ALTER INDEX index_id_text INVISIBLE;
再次查看表index13的索引:
注意如果出现图片中的字样,说明已经被隐藏了。
有兴趣的小伙伴,可以自行插入数据进行测试。
简单粗暴的测试:插入上千万条数据,在表没有索引的情况下进行查询和表有索引的情况下进行查询,然后再对比两者所用的时间,就可以知道结果啦!
取消隐藏:
alter table index13 ALTER INDEX index_id_text VISIBLE;
再次查看表index13的索引:
六、删除索引
所谓删除索引,就是删除表中已经创建的索引。之所以要删除索引,是因为这些索引会降低表的更新速度,影响数据库的性能。
drop INDEX 索引别名 ON 表名;
例:
drop INDEX index_id_text ON index13;
查看:
表index13的索引已经被删除了。
七、修改索引
最好的办法就是:先删除,后增加。
总结:
MySQL的索引操作已经全部记录下来了,可以根据项目需要进行变更。索引对于数据查询还是有很多好处的,如果表中有索引,且需要插入大量数据时,推荐先删除然后再进行插入。
今天是冬至,加班写下这篇博客,记录笔记并分享,希望对看到此篇博客的小伙伴有帮助。❀冬至快乐❀