1、索引的介绍
- 索引是通过某种算法来构建一个数据模型,用于快速找出在某个列中有一特定值的行。不使用索引时,mysql必须从第一条记录开始读完整个表,直到找到相关的行,表越大,查询花费的时间就越久,如果表中查询的列有一个索引,则能快速到达这一位置去搜索数据文件
- 索引类似文件的目录
2、索引的分类
-
索引是存储引擎用来快速查找记录的一种数据结构,按照实现的方式分类,主要有Hash索引和B+Tree索引
-
按功能划分,索引有:
-- 单列索引:普通索引、唯一索引、主键索引
-- 组合索引
-- 全文索引
-- 空间索引
3、索引的操作
3.1、单列索引
- 一个索引只包含单个列,但一个表中可以有多个单列索引
3.1.1、普通索引
-
普通索引是mysql中的基本索引,没什么限制,允许在定义索引的列中插入重复值和空值,纯粹是为了加快查询数据速度
-
创建普通索引
mysqlcreate database demo_index; use demo_index; -- 创建表时直接指定 create table student( sid int primary key, card_id varchar(16), name varchar(8), gender enum('男', '女'), age int(4), birthday date, phone_num varchar(16), chinese_score double, index index_name(name) -- 给name列创建名字为index_name的索引 )charset = utf8; -- 创建完表后再创建索引 create index indexname on table_name(column_name); create index index_gender on student(gender); -- 修改表结构的方式添加索引 alter table table_name add index indexname(column_name); alter table student add index index_age(age);
3.1.2、查看索引
-
查看某数据库中所有的索引
mysqlselect * from mysql.'innodb_index_stats' a where a.'database_name' = '要查看的数据库名'; -- 查找demo_index数据库中所有的索引 select * from mysql.'innodb_index_stats' a where a.'database_name' = demo_index;
-
查看表中所有索引
mysqlselect * from mysql.'innodb_index_stats' a where a.'database_name' = '要查看的表所在的数据库名' and a.table_name like '%表名%'; -- 查看student表中所有的索引 select * from mysql.'innodb_index_stats' a where a.'database_name' = demo_index and a.table_name like '%student%'; show index from table_name; show index from student;
3.1.3、删除索引
-
语法
mysqldrop index index_name on table_name; -- or alter table table_name drop index index_name;
-
示例
mysqldrop index index_gender on student; alter table student drop index index_age;
3.1.4、唯一索引
-
唯一索引与普通索引类似,区别是索引列的值必须唯一,但允许有空值;如果是组合索引,则列值的组合必须唯一
-
唯一索引的创建
mysql-- 创建表时同时创建索引 create table student1( sid int primary key, car_id varchar(16), name varchar(8), gender enum('男', '女'), age int(4), birthday date, phone_num varchar(16), chinese_score double, unique index_car_id(car_id) --给car_id列创建唯一索引 )charset = utf8; -- 使用create创建唯一索引 create unique index index_name on table_name(column_name); create unique index index_sid on student1(sid); -- 使用alter...add创建唯一索引 alter table table_name add unique index_name(column_name); alter table student1 add unique index_phone_num(phone_num);
3.1.5、主键索引
- 每张表通常都会有自己的主键,当我们创建带主键的表时,mysql会自动在主键列上建立一个索引,这就是主键索引。
- 主键是具有唯一性且不能为null,所以是一种特殊的唯一索引。
3.2、组合索引
-
组合索引也叫复合索引,是我们在建立索引时使用多个字段,例如同时使用身份证和手机号码建立索引,同样的可以建立普通索引或唯一索引
-
组合索引的使用符合最左原则
-
组合索引创建语法
mysql--创建普通复合索引 create index index_name on table_name(column1(length), column2(length)); --创建唯一复合索引 create unique index index_name on table_name(column1, column2); --column列表的顺序对使用有影响,即最左原则
-
示例
mysqlcreate index index_phone_name on student(phone_num, name); select * from student where name = 'jack'; --where条件只使用了name,虽然name在组合索引中,但不在最左侧,无法引用 select * from student where phone_num = '151000000'; select * from student where phone_num = '151000000' and name = 'jack'; select * from student where name = 'jack' and phone_num = '151000000'; --这3条sql都能使用到索引index_phone_name,后2条语句在mysql中是等价的
3.3、全文索引fulltext
-
fulltext主要用来查找文本中的关键字,而不是直接与索引中的值相比较,他更像一个搜索引擎,基于相似度的查询,而不是简单的where语句的参数匹配
-
用like+%就可以实现模糊匹配了,为啥还要fulltext?like+%在文本比较少的时候是适合的,但对于大量的文本数据检索,是不可想象的,在大量的数据面前,like+%的速度与fulltext是数量级的差别,但fulltext存在精度问题
-
全文索引的版本、存储引擎、数据类型的支持情况
-- mysql5.6以前的版本,只有myISAM存储引擎支持全文索引;
-- mysql5.6及以后的版本,myISAM和innoDB存储引擎均支持全文索引;
-- 只有字段的数据类型为char、varchar、text及其系列才可以建全文索引;
-- 在数据量较大的时候,先将数据放入一个没有全局索引的表中,然后再用create创建fulltext索引,要比先为一张表建立fulltext然后再将数据写入的速度快很多;
-- 测试或使用fulltext时,需要先看一下自己的mysql版本、存储引擎和数据类型是否支持全文索引
-
fulltext有两个变量,最小搜索长度(min_word_len)和最大搜索长度(max_word_len),对于长度小于最小搜索长度和大于最大搜索长度的词语,都不会被索引。也就是对一个词语使用全文索引搜索,那这个词的长度必须在最小搜索长度和最大搜索长度之间。可以使用以下命令查看这两个默认值
mysqlshow variables like '%ft%'; --innodb中最小长度为3,最大长度为84
-
创建全文索引
mysql--创建表的时候创建全文索引,这种方式速度较低 create table text_article( id int primary key auto_increment, title varchar(255), content varchar(1000), writing_date date, fulltext(content) )charset = utf8; --创建完表后使用alter添加fulltext alter table text_article add fulltext index_content(content); --使用create创建全文索引 create fulltext index index_content on text_article(content);
-
fulltext的使用
mysqlmatch(column1,column2...) against(expr[search_modifier]) select * from text_article where match(content) against('my'); --没有结果,单词数需要≥3 select * from text_article where match(content) against('you'); select * from text_article where content like '%you%'; --查询速度没有fulltext快
3.4、空间索引
-
mysql在5.7之后支持空间索引,且支持openGIS几何数据模型
-
空间索引是对空间数据类型的字段建立的索引,mysql中的空间数据类型有:geometry、point、linestring、polygon共4种
-
mysql使用spatial关键字进行扩展,使得能够用于创建正规索引类型的语法创建空间索引
-
创建空间索引的列必须声明为not null
-
空间索引一般用的比较少
类型 含义 说明 geometry 空间数据 任何一种空间类型 point 点 坐标值 linestring 线 由一系列点连接而成 polygon 多边形 由多条线组成 -
示例
mysqlcreate table school_info( id int primary key auto_increment comment 'id', school_name varchar(16) comment '学校名称', geom_point geometry not null comment '经纬度', spatial key index_geom(geom_point) )charset = utf8;
4、索引的原理
4.1、概述
- 通常索引本身也很大,不可能都存储在内存中,所以往往以索引文件的形式存储在磁盘上
- 正因此,索引查找过程就需要产生磁盘i/o消耗,i/o存取消耗要比内存存取高几个数量级
- 评价一个数据结构作为索引的优劣最重要的指标就是查找过程中磁盘i/o操作次数的复杂程度
- 所以所以的结构组织要尽量减少查找过程中磁盘i/o的存取次数
4.2、相关算法
4.2.1、hash算法
- 优点:通过字段的值计算的hash值,定位数据非常快
- 缺点:不能进行范围查找,无法进行大小的比较
4.2.2、二叉树
- 特性:分为左子树、右子树和根节点,左子树比根节点的值小,右子树比根节点的值大
- 确定:可能产生不平衡,类似链表的结构
4.2.3、平衡二叉树
-
特点:
-- 左子树和右子树都是平衡二叉树
-- 左子树比中间小,右子树比中间大
-- 左子树和右子树的深度差不超过1
-
缺点:
-- 插入操作需要旋转
-- 支持范围查找,但需要回旋查询,效率较低
-- 如果存放数据量较大,树高度越高,查询效率越慢
4.2.4、BTree树
- 目前大部分数据库系统及文件系统都采用B-Tree或B+Tree作为索引结构
5、索引的特点
5.1、优点:
- 大大加快数据查询速度
- 使用分组和排序查询数据时,可以显著减少查询时分组和排序的时间
- 创建唯一索引能够保证数据库表中每一行数据的唯一性
- 在实现数据的参考完整性方面,可以加快表和表之间的连接
5.2、缺点:
- 索引的创建和维护需要消耗时间,且随着数据量的增加而增加
- 索引需要占据磁盘空间
- 对数据表中的数据进行增、删、改操作时,索引也需要动态的维护,降低了维护 速度
6、索引的创建原则
- 更新频繁的列不应设置为索引
- 数据量小的表不需要索引
- 重复的数据多的字段不应设为索引,通常重复超过15%的字段就不应设置为索引
- 应优先考虑对where和order by字段的列建立索引