Bootstrap

MySQL-索引

索引是什么?

索引是帮助mysql高效获取数据的数据结构(有序)

优点:提高数据检索的效率,降低数据库的io成本,通过索引列对数据进行排序,降低排序的成本,降低cpu的消耗

缺点:索引列也是要占用空间的,索引大大提高了提高了查询效率,同时却也降低了更新表的速度

索引结构分类:

B+tree索引

Hash索引 通过hash表实现,只能实现精确匹配查询才有效,不支持范围查询

R-tree空间索引 空间索引是MYISAM的一种特殊索引类型,主要用于地理空间数据类型,通常使用较少

Full-text全文索引 是一种通过建立倒排索引,快速匹配文档的方式,类似于LUcene,SOlr,Es

b树:

在这里插入图片描述

b+树

在这里插入图片描述

在这里插入图片描述

为什么InnoDB存储引擎选择使用B+tree索引结构?

相对于二叉树,层级更少,搜索效率高

对于b树来说,无论是叶子节点还是非叶子节点,都会保留数据,这样导致一页中存储的键值减少,指针跟着减少,要同意保存大量数据,只能增加树的高度,导致性能降低

索引结构:
索引结构描述
B+Tree索引最常见索引类型,大部分都支持
hash索引底层用hash表实现的,不支持范围查询
R-tree空间索引是mylsam引擎的一个特殊索引类型,主要用于地理空间数据类型
full-text是一种倒排索引,快速匹配文档的方式

为什么选择使用B+tree索引结构?

相对于二叉树,层级更少,搜索效率高;

对于B-tree,无论是叶子节点还是非叶子节点,都会保存数据,这样导致一页中存储的键值减少,指针跟着减少,要同样保存大量数据,只能增加树的高度,导致性能降低;

相对Hash索引l,B+tree支持范围匹配及排序操作;

索引分类:
  • 主键索引:针对表中主键创建的索引,默认自动创建,只能有一个
  • 唯一索引: 避免同一个表中某数据列中的值重复
  • 常规索引: 快速定位特定数据
  • 全文索引: 全文索引查找的是文本中的关键词,而不是比较索引中的值

在InnoDB下根据索引的存储形式,又可以分为以下两种:

  • 聚集索引 将数据存储与索引放到一块,索引结构的叶子节点保存了行数据 (必须有,而且只能有一个)

选取规则:

如果存在主键,主键索引就是聚集索引,如果不存在,将使用第一个唯一索引作为聚集索引

如果表中没有主键或者合适的唯一索引,则InnoDB会自动生成一个rowid作为隐藏的聚集索引

  • 二级索引 将数据和索引分开存储,索引结构的叶子节点关联的是对应的主键
索引语法
create (unique|fulltext) index index_name on table_name (index_col_name)创建索引

show index from table_name 查看索引

drop index index_name on table_name; 删除索引
sql性能分析:

show global status like 'Com_______'  7个下划线查看每种操作的次数

show variables like 'slow_query_log' 查看慢查询日志是否开启

show variables like 'slow_query_log_file'查看慢查询日志的位置

profile详情能够在做sql优化帮助我们了解 

select @@have_profiling;查看是否支持

show profiles 查看每一条sql耗时的基本情况

show profile for query query_id 查看指定的query_id的sql语句各个阶段的耗时情况

show profile cpu for query query_id查看cpu的使用情况

直接在sql语句前面加上explain

在这里插入图片描述

id : select查询的序列号,表示查询中执行的select子句或者操作表的顺序(id相同,执行顺序从上到下,id不同值越大越先执行

select_type:表示select的类型,常见的取值有simple(简单表,即不使用表连接或者子查询),primary(主查询,即外层的查询),union(union中第二个或者后面的查询语句),subquery(select/where之后包含了子查询),derived包含在from子句中的子查询
type: 表示连接类型,性能由好到查的连接类型为NULL,system,const(主键或者唯一索引),eq_ref,ref(用非唯一性的索引),range,index,all

key: 实际使用的索引,如果为NULL,则没有使用索引

key_len:表示索引使用的字节数,该值为索引字段最大可能长度,并非实际使用长度,在不损失精确性的前提下,长度越短越好

row:mysql认为必须要执行查询的行数,在innodb引擎中是一个估计值,可能并不总是准确的

filtered:表示返回结果的行数,占需读取行数的百分比,filtered的值越大越好

extra:using index condition 查询使用了索引但是需要回表查询数据,using where ,using index 查询使用了索引,但是需要的数据都在索引列中能找到,所以不需要回表查询数据

索引的使用:

最左前缀法则:

如果索引了多列(联合索引),要遵守最左前缀法则,最左前缀法则指的是查询从索引的最左列开始,并不跳过索引中的列

如果跳跃某一列,索引将部分失效(后面的字段索引失效)

注:mysql8之后优化器优化了最左前缀法则,可以进行跳跃,顺序也可以打乱

索引列运算:

不要在索引列进行运算操作,索引将失效

字符串不加引号:

字符串类型字段使用时,不加引号,索引将失效

模糊查询

如果仅仅是尾部模糊匹配,索引不会失效,如果是头部模糊匹配,索引失效

or连接的条件:

用or分割开的条件,如果or前的条件中的列有索引,而后面的列中没有索引,那么涉及的索引都不会被用到

覆盖索引:

尽量使用覆盖索引(查询使用了索引,并且需要返回的列,在该索引中已经全部能够找到),减少select *就是减少回表操作

前缀索引:

当前字段类型为字符串时,有时候需要索引很长的字符串,这会让索引变得很大,查询时,浪费大量的磁盘io,影响查询效率,

此时可以只将字符串的一部分前缀,建立索引,这样可以大大节约索引空间,从而提高索引效率

create index 名字 table名字(clomn(n))
索引下推

现在我们知道,对于联合索引(a, b),在执行 select * from table where a > 1 and b = 2 语句的时候,只有 a 字段能用到索引,那在联合索引的 B+Tree 找到第一个满足条件的主键值(ID 为 2)后,还需要判断其他条件是否满足(看 b 是否等于 2),那是在联合索引里判断?还是回主键索引去判断呢?

  • 在 MySQL 5.6 之前,只能从 ID2 (主键值)开始一个个回表,到「主键索引」上找出数据行,再对比 b 字段值。
  • 而 MySQL 5.6 引入的索引下推优化(index condition pushdown), 可以在联合索引遍历过程中,对联合索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数

当你的查询语句的执行计划里,出现了 Extra 为 Using index condition,那么说明使用了索引下推的优化。

Sql提示:

如果有满足多个索引的话,mysql会使用列多的那个索引

use index()你用哪个索引

ignore index()你不用哪个索引

force index()你必须用这个索引
索引的设计原则

1.针对于数据量较大,且查询比较频繁的表建立索引。

2.针对于常作为查询条件(where)、排序(order by)、分组(group by)操作的字段建立索引l。

3.尽量选择区分度高的列作为索引,尽量建立唯一索引,区分度越高,使用索引的效率越高。

4.如果是字符串类型的字段,字段的长度较长,可以针对于字段的特点,建立前缀索引。

5.尽量使用联合索引,减少单列索引,查询时,联合索引很多时候可以覆盖索引,节省存储空间,避免回表,提高查询效率。

6.要控制索引的数量,索引并不是多多益善,索引越多,维护索引结构的代价也就越大,会影响增删改的效率。

7.如果索引I列不能存储NULL值,请在创建表时使用NOTNULL约束它。当优化器知道每列是否包含NULL值时,它可以更好地确定哪个索引最有效地用于查询。

;