介绍:
索引是通过某种算法,构建出一个数据模型,用于快速找出在某个列中有一特定值的行,不使用索引,MySQL必须从第一条记录开始读完整个表,直到找出相关的行,表越大,查询数据所花费的时间就越多,如果表中查询的列有一个索引,MySQL能够快速达到一个位置去搜索数据文件,而不必查看所有数据,那么将会节省很大一部分时间。
分类
索引是存储引擎用来快速查找的记录的一种数据结构,按照实现的方式类分,主要有HASH索引和B+TREE索引
创建索引
单列索引:一个索引只包含单个列,但一个表中可以有多个单列索引
普通索引:MySQL中基本索引类型,没有什么限制,允许在定义索引的列中插入重复值和控制,纯粹为了查询数据快一点。
单列索引
普通索引
创建操作
例如:
CREATE DATABASE mydb5;
USE mydb5;
-- 方式一 -创建表的时候直接指定
CREATE TABLE student(
sid INT PRIMARY KEY,
card_id VARCHAR(50),
name VARCHAR(50),
gender VARCHAR(20),
age INT,
birth DATE,
phone_num VARCHAR(20),
score DOUBLE,
INDEX index_name(name) -- 给name列创建索引
);
SELECT * FROM student WHERE name='张三';
-- 第二种方式 - 直接创建
CREATE INDEX index_gender ON student(gender);
-- 第三种方式 - 修改表结构(添加索引)
ALTER TABLE student ADD INDEX index_age(age);
查看操作
例如:
-- 1.查看数据库所有索引
SELECT * FROM mysql.innodb_index_stats a WHERE a.database_name='mydb5';
-- 2.查看表中所有索引
SELECT * FROM mysql.innodb_index_stats a WHERE a.database_name = 'mydb5' AND a.table_name LIKE '%student%';
-- 3.查看表中所有索引
SHOW INDEX FROM student;
删除索引
方法:
DROP INDEX 索引名 ON 表名
或
ALTER TABLE 表名 DROP INDEX 索引名
例如:
-- 删除索引
DROP INDEX index_gender ON student;
ALTER TABLE student DROP INDEX index_age;
唯一索引
概念:唯一索引与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。
添加索引
例如:
-- 方式一 -创建表的时候直接指定
CREATE TABLE student2(
sid INT PRIMARY KEY,
card_id VARCHAR(50),
name VARCHAR(50),
gender VARCHAR(20),
age INT,
birth DATE,
phone_num VARCHAR(20),
score DOUBLE,
UNIQUE index_card_id(card_id) -- 给card_id列创建索引
);
-- 第二种方式 - 直接创建
CREATE UNIQUE INDEX index_gender ON student2(gender);
-- 第三种方式 - 修改表结构(添加索引)
ALTER TABLE student ADD UNIQUE INDEX index_age(age);
删除索引
方法:
DROP INDEX 索引名 ON 表名
或
ALTER TABLE 表名 DROP INDEX 索引名
例如:
-- 删除索引
DROP INDEX index_gender ON student2;
ALTER TABLE student2 DROP INDEX index_age;
主键索引
概念:每张表一般都会有自己的主键,当我们在创建表时MySQL会自动在主键列上建立一个索引,这就是主键索引。主键是具有唯一性且不允许为NULL,所以他是一种特殊的唯一索引。
例如:
-- 主键索引
SHOW INDEX FROM student2;
-- 此时能看到主键索引,但是无法在可视化界面中看到,并且为自动创建
组合索引
概念:
- 组合索引又叫做复合索引,指的是我们在建立索引的时候使用多个字段,例如同时使用身份证和手机号建立索引,同样的也以建立普通索引或是唯一索引。
- 复合索引的使用复合最左原则
方法:
CREATE INDEX indexname ON table_name (column1(length),column2(length));
例如:
-- 创建普通索引
CREATE INDEX index_phone_name ON student(phone_num,name);
-- 删除索引
DROP INDEX index_phone_name ON student;
-- 创建唯一索引
CREATE UNIQUE INDEX index_phone_name ON student(phone_num,name);
全文索引
概念:
-
全文索引的关键字是fulltext
-
全文索引主要用来查找文本中的关键字,而不是直接与索引中的值相比较,它更像是一个搜索引擎,基于相似度的查询没不是简单的where语句的参数匹配。
-
用like+%就可以实现模糊匹配了,但是这种方式当数据较少时合适,对于大量的文本数据检索,是不行的。全文检索在大量数据中,比like+%的速度快得多,但是全文检索存在精度问题
-
MySQL5.6之前,只有MyISAM存储引擎支持全文索引
-
MySQL5.6之后,MyISAM和InnoDB存储引擎均支持全文索引
-
只有字段的数据类型为char、varchar、text及其系列才可以建全文索引
-
在数据较大时,先将数据放入一个没有全局索引的表中,然后再用craete index创建fulltext索引,要比先为一张表建立fulltext然后在降数据写入的速度快很多
-
测试或使用全文索引时,要先看自己的MySQL版本、存储引擎和数据类型是否支持全文索引。
MySQL中的全文索引有两个变量,最小搜索长度和最大搜索长度。对于长度小于最小搜索长度和最大搜索长度的词语,都不会被索引。这两个默认值可以使用以下命令查看:
SHOW VARIABLES LIKE ‘%ft%’
全文索引的操作
例如:
CREATE table t_article(
id INT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(255),
content VARCHAR(10000),
writing_date DATE
-- FULLTEXT(content) 创建全文索引
);
insert into t_article values(null,"Yesterday Once More","When I was young I listen to the radio",'2021-10-01');
insert into t_article values(null,"Right Here Waiting","Oceans apart, day after day,and I slowly go insane",'2021-10-02');
insert into t_article values(null,"My Heart Will Go On","every night in my dreams,i see you, i feel you",'2021-10-03');
insert into t_article values(null,"Everything I Do","eLook into my eyes,You will see what you mean to me",'2021-10-04');
insert into t_article values(null,"Called To Say I Love You","say love you no new year's day, to celebrate",'2021-10-05');
insert into t_article values(null,"Nothing's Gonna Change My Love For You","if i had to live my life without you near me",'2021-10-06');
insert into t_article values(null,"Everybody","We're gonna bring the flavor show U how.",'2021-10-07');
-- 修改表结构添加全文索引
ALTER TABLE t_article ADD FULLTEXT index_context(content);
-- 添加全文索引(和上面的修改二选一即可)
CREATE FULLTEXT INDEX index_context ON t_article(content);
-- 使用全文索引
SELECT * FROM t_article WHERE MATCH(content) AGAINST('yo'); -- 没有结果(原因是最小查询值问题)
SELECT * FROM t_article WHERE MATCH(content) AGAINST('you'); -- 有结果
空间索引
概念:
- MySQL在5.7之后支持空间索引,支持OpenGIS几何数据模型
- 空间索引是对空间数据类型的字段建立的索引,MySQL中的空间数据类型4种,分别是GEOMETRY、POINT、LINESTRING、POLYGON.。
- MySQL使用SPATIAL关键字进行扩张,是的能够用于创建正规索引类型的语法创建空间索引。
- 创建空间索引的列,必须将其声明为NOT NULL。
- 空间索引一边是用的比较少,了解即可
类型 | 含义 | 说明 |
---|---|---|
Geometry | 空间数据 | 任何一种空间类型 |
Point | 点 | 坐标值 |
LineString | 线 | 有一系列点连接而成 |
Polygon | 多边形 | 由多条线组成 |
例如:
create table shop_info (
id int primary key auto_increment comment 'id',
shop_name varchar(64) not null comment '门店名称',
geom_point geometry not null comment '经纬度',
spatial key geom_index(geom_point)
);
内部原理
概念:
- 一般来说索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储在磁盘上。
- 这样的话,索引查找过程中就要产生磁盘I/O消耗,相对于内存存取,I/O存取的消耗要高几个数量级,所以评价一个数据结构作为索引的优劣最重要的指标就是在查找过程中磁盘I/O操作次数的渐进复杂度。
- 换句话说,索引的结构组织要尽量减少查找过程中磁盘I/O的存取次数。
Hash算法
优点:通过字段的值计算的Hash值,定位数据非常快
缺点:不通进行范围查找,因为散列表中的值是无序的,无法进行大小的比较。
二叉树和二叉平衡树
二叉树
优点:分为左子树、右子树和根节点,左子树比根节点值要小,右子树比根节点要大
缺点:有可能产生不平衡类似于链表的结构
平衡二叉树
优点:
- 它的左子树和右子树都是平衡二叉树
- 左子树比中间小,右子树比中间值大
- 左子树和右子树的深度之差的绝对值不超过1
缺点: - 插入操作需要旋转
- 支持范围查询,但回旋查询效率较低,比如查询大于8的,会回旋到父节点7、10
- 如果存放几百条数据的情况下,树高度越高,查询效率越慢
BTREE树模型
目前大部分数据系统及文件系统都采用B-TREE或其变种B+TREE作为索引结构,BTREE结构可以有效地解决之前的相关算法遇到的问题。
BTREE树 索引应用
MyISAM引擎使用B+TREE作为索引结构,叶节点的data域存放的是数据记录的地址。
索引的特点
优点
- 大大加快数据的查询速度
- 使用分组和排序进行数据查询时,可以显著减少查询时分组和排序的时间
- 创建唯一索引,能够保证数据库表中每一行数据的唯一性
- 在现实数据的参考完整性方面,可以加速表和表之间的连接
缺点
- 创建索引和维护索引需要消耗时间,并且随着数据量的增加,时间也会增加
- 索引需要占据磁盘空间
- 对数据表中的数据进行增删改时,索引也要动态维护,降低了维度的速度
创建索引的原则
- 更新频繁的列不应设置索引
- 数据量小的表不要使用索引
- 重复数据多的字段不应设为索引
- 首先应该考虑对where和order by涉及的列上建立索引