索引的作用是帮助Mysql
高效的获取数据
中的数据结构(有序),在数据之外,数据库系统还维护着满足特定的查找算法的数据结构,这些数据结构通过某种方式引用指向数据,这样就可以在这些数据结构之上实现高级的查找算法,这种数据结构就是索引。 一般来说索引本身也是十分的大,不可能全部存储在内存中,因此索引往往会通过索引的文件形式存储在磁盘上,索引是数据库中用来提高性能的最常用的工具。
对于没有建立索引的数据表,每一次的查询的操作都是从上到下的进行遍历的操作,也就是说只有找到对应的数据,才遍历成功。
建立索引的作用是对数据库表中的一列或者多列的值进行一种排序的一种结构(B树),使用索引能够快速的访问数据库表中的特定的信息。
- 类似于书籍的索引的操作,提高数据的检索的效率,降低数据的成本
- 通过索引列的对数据进行排序的操作,降低数据的排序的成本,降低CPU的性能的消耗
- 实际上索引也是一张表,该表保存了主键和索引的字段,并且指向了实体类的记录,所以索引列也是要占据空间的。
- 索引虽然能够提高了查询的效率,但是同时却也降低了更新表的速度,比如对于表进行增、删除、修改的操作。因为更新表的时候,Mysql不仅仅要保存数据,还要保存一下索引文件每一次更新提那家索引列的字段。都会调整因为更新之后所带来的键值对的变化的索引的信息。
索引 是在mysql的存储的引擎层实现的,而不是在服务器层实现的,所以每种存储引擎的索引都是不一定完全的相同,也不是所有的存储的引擎都是支持所有的索引类型的,Mysql目前提供了下面的4 中索引。
- b tree : 最常见的索引的类型,使用的场景比较简单。
- Hash ;只有Memory 引擎能够支持,使用的场景比较简单。
- R tree 空间的索引: 空间的索引是MylSAM 引擎的一个特殊索引类型,主要用于地理空间的数据类型,通常使用的比较少,不做特别的说明。
- Full-text 全文的索引: 全文的索引也是MylSAM 中的一个特殊的引用类型,主要用于全文的索引。
平时如果没有说的索引,都是指B+树(多路搜索树,并不一定是二叉)结构组织的索引。其中的聚集索引、前缀索引、唯一的索引都是默认使用B+树索引,统称为索引。
BTree 又叫做多路平衡搜索树,一颗m叉的BTree 特性如下:
- 树中的每个节点最多的包含m个孩子。
- 除了根节点和叶子节点之外,每个节点至少有ceil(m/2)个孩子
- 如果根节点不是叶子节点,则至少会有两个孩子
- 所有的叶子节点都是在同一层。
- 每一个非叶子节点由n个key与n+1 个指针组成,其中 ceil(m/2) - 1 <= n < = m-1
B+ 树 是B Tree的变种,B+树和B树的区别:
- n叉B+树最多含N个key,而BTree最多含有 n-1 个key。
- B+树的叶子节点保存所有的key信息,依照key的大小进行顺序的排序。
- 所有的非叶子节点都可以看做是key的索引的部分。
- 单值索引:既一个索引仅仅只能包含单个列,一个表可以有多个单列索引。
- 唯一索引:索引列的值必须唯一,但允许有空值。
- 复合索引:即一个索引包含多个列。
- 主键索引:主键会自动的帮助我们创建一个索引叫做主键索引。
在创建表的时候建立索引操作,注意主键ID数据库引擎会给其索引
-- 在book表中的year_publication字段上建立普通索引
CREATE TABLE book
(
bookid INT NOT NULL,
bookname VARCHAR(255) NOT NULL,
authors VARCHAR(255) NOT NULL,
info VARCHAR(255) NULL,
comment VARCHAR(255) NULL,
year_publication YEAR NOT NULL,
-- 表示的是普通的索引
INDEX(year_publication)
);
-- 使用EXPLAIN语句查看索引是否正在使用
explain select * from book where year_publication=1990;
-- 创建一个表t1,在表中的id字段上使用UNIQUE关键字创建唯一索引
CREATE TABLE t1
(
id INT NOT NULL,
name CHAR(30) NOT NULL,
UNIQUE INDEX UniqIdx(id)
);
-- 创建一个表t2,在表中的name字段上使用创建单列索引
CREATE TABLE t2
(
id INT NOT NULL,
name CHAR(50) NULL,
INDEX SingleIdx(name(20))
);
-- 创建表t3,在表中的id,name和info字段上建立组合索引
CREATE TABLE t3
(
id INT NOT NULL,
name CHAR(30) NOT NULL,
age INT NOT NULL,
info VARCHAR(255),
INDEX MultiIdx(id, name, info(100))
);
-- 创建表t4,在表中的info字段上建立全文索引
CREATE TABLE t4
(
id INT NOT NULL,
name CHAR(30) NOT NULL,
age INT NOT NULL,
info VARCHAR(255),
FULLTEXT INDEX FullTxtIdx(info)
) ENGINE=MyISAM;
-- 创建表t5,在空间类型为GEOMETRY的字段上创建空间索引
CREATE TABLE t5 (
g GEOMETRY NOT NULL,
SPATIAL INDEX spatIdx ( g )
) ENGINE = MyISAM;
show index from table_name;
show keys from table_name;
-- 删除book表中的名称为UniqidIdx的唯一索引
ALTER TABLE book DROP INDEX UniqidIdx;
-- 删除book表中名称为BkAuAndInfoIdx的组合索引
DROP INDEX BkAuAndInfoIdx ON book;
-- 创建普通的索引
ALTER TABLE table_name ADD INDEX index_name (Att_name_1);
索引的设计可以遵循一些已经存在的原则,创建索引的时候请尽量考虑符合的这些的原则,便于提升索引的使用的效率,更高效的使用索引。
- 对于查询的频次较高,但是数据量比较大的表建立索引。
- 索引字段的选择,最佳候选应当从where子句中的条件中提取出来,如果where子句中的组合比较作,那么应当挑选最常使用的,过滤效果最好的列的组合。
- 使用唯一索引,区分度越高,使用的索引的效率越高。
- 索引可以有效的提升查询数据的效率,但是索引的数量不是多多益善,索引越多维护索引的代价自然就很大。对于插入、更新、删除等DML操作比较频繁的表来说,索引过多,会引入相当高的维护的代价,降低DML操作的效率,增加相对应的操作的时间。另外索引过多的话,MySQL也会犯选择困难的病症,虽然最终仍然会找到一个可用的索引,但是无疑会提高了选择的代价。
- 使用短索引,索引创建之后也是使用硬盘来进行存储的,因此提升索引访问IO效率,也可以提升总体的访问的效率,加入构成索引的总长度比较短,那么在给定大小的存储块内可以存储更多的索引的值,相应的可以有效的提升MySQL访问索引的IO效率。
- 利用最左前缀,N个列组合组成的组合索引,那么相当于是创建了N个索引,如果查询时where子句中使用了组成索引的前几个字段,那么这条查询SQL可以利用组合索引来提升查询的效率。
索引是数据库优化最常用也是最重要的手段之一,通过索引通常能够帮助用户解决大多数的MySQL的性能的问题。索引的应用的场景是在多条的数据中才能够实现操作。
数据库的优化的操作能够通过索引来实现。
select *
from salaries
where emp_no = 10009;
-- 此时存在索引
show index from salaries;
select *
from salaries
where salary = 60117;
-- 添加索引操作
create index idx_employee_salary on salaries(salary);
-- 创建索引之后的查询操作,查询速度快速上升
select *
from salaries
where salary = 66074;
总结:索引是数据库优化的重要的手段之一,能够优化查询的效率
在索引的使用的验证中,我们能够通过explain来进行判断操作,判断时候经历过索引的操作,其中的type中的ALL表示的是全表的扫描操作,Ref表示的是走过索引类型,其中的key_len表示的是索引的长度,也就是索引执行的长度。
在使用explain下,会出现的表单中含有的数据是extra中包含的元素包括
- using index : 使用覆盖索引的时候就会出现
- using where: 在查找使用索引的情况下,需要回表查询所需要的数据。
- using index condition :查找使用了索引,但是需要回表查询数据。
- using index;using where :查找使用了索引,但是需要的数据都在索引列中能够找到,所以不需要回表查询数据。
比如说:4 中通过索引查找到了指定的信息,但是需要通过回表的操作,回到数据表中查询指定的条件的数据。然后进行输出的操作。
- 全值匹配,对于索引中所有列都是有指定具体值。
- 最左前缀法则:
- 范围查询,右边的列,不能够使用索引
- 在某一列上使用了运算操作,索引将失效
- 字符串不加单引号,造成索引失效
- 尽量使用覆盖索引,避免使用select*
- 使用or分割的条件
- 通过%开头的like模糊查找,索引失效
- 如果mysql评估使用索引比全表扫描更慢,则不使用索引。
- is NULL 和 NOT NULL有时候会出现索引失效。
对于索引中的所有的列都能够指定具体的值,这个时候,索引生效,执行的效率较高。
如果索引了多列,需要遵循最左的前缀法则。指的是查询从最左前列开始,并且不会跳过索引中间的列。否则就不会走索引的操作。
范围查询右边的列,不能够使用索引。根据前面的两个字段name,status,查询是走索引的,但是最后的一个条件address没有用到索引
如果在某个列上进行运算操作,索引将失效
字符串不加单引号,造成索引失败。
尽量使用覆盖索引,能够有效的避免select*,如果使用的是select* * 的操作,那么就会出现的操作是using index condition 的操作,查找中使用了索引,但是还是需要进行回表查询数据的操作。如果使用的是select name ,status 等条件,则Extra下面会出现 using where;using index,表示的是查找中使用了索引,但是需要的数据都在索引列总找到,所以不需要进行回表查询的操作。
使用or分割的条件,如果or前面的条件中的列有索引,而后面的列中没有索引,那么涉及的索引都不会被用到。示例:name 字段是索引列,而 create_time 不是索引列,中间是通过or连接的,是不走索引的。如果将or换成and,那么也将会走索引的操作,扫描的是一行的记录
通过% 开头的like模糊查找,索引失效,如果仅仅是尾部模糊匹配,索引不会失效。如果此时能够能够避免覆盖索引的操作,其中的筛选的条件是索引固定的内容,那么就会通过索引进行查询,如果select 条件中没有索引固定的内容,那么就会出现不会走索引的情况。总结:对于模糊查找不能够通过索引的方式显示,那么就通过使用覆盖索引的方式实现操作。
如果MySQL评估使用索引比全表更慢,即不使用索引。也就是说数据量比较大,某一条数据占得比重比较大,所以这个时候就不会使用索引的操作方式,而是采用全表的扫描的形式进行实现。
is NUll ,is Not NULL有时会出现索引失效的情况存在。
in : 表示的是使用索引
not in : 表示的是索引失效,即总结得出,在编写SQL语句的时候尽量多使用in 而非not in
尽量使用复合索引操作,而少使用单列索引的操作。
创建复合索引的操作
create index idx_name_sta_address on tb_Seller(name,status,address);
-- 相当于创建三个索引
name
name + status
name + status + address
-- 数据库会选择一个最优的索引来使用后,并不会使用全部的索引
-- 对于辨识度最高的,将作为数据库的使用的优先选择的条件。
-- 表示的是当前会话的索引的使用情况
show status like 'Handler_read%';
-- 表示的是全局的索引的使用情况
show global status like 'Handler_read%'