前言
2022/8/2 19:42
暑假学习ing
推荐
【MySQL数据库教程天花板,mysql安装到mysql高级,强!硬!-哔哩哔哩】
第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
可以设置索引为全文索引。在定义索引的列上支持值的全文查找,允许在这些索引列中插入重复值和空值。全文索引只能创建在CHAR
、VARCHAR
或TEXT
类型及其系列类型的字段上,查询数据量较大的字符串类型的字段时,使用全文索引可以提高查询速度。例如,表student
的字段information
是TEXT
类型,该字段包含了很多文字信息。在字段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全文索引可以用于全文搜索,并且只为CHAR
、VARCHAR
和TEXT
列创建索引。索引总是对整个列进行,不支持局部(前缀)索引。
举例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 ('查询字符串');
明显提高效率。
注意点
- 使用全文索引前,搞清楚版本支持情况;
- 全文索引比 like + % 快 N 倍,但是可能存在精度问题;
- 如果需要全文索引的是大量数据,建议先添加数据,再创建索引。
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。