索引
概述
索引 index 帮助MySQL高效获取数据的数据结构(有序)。在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用数据,这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引。
索引结构
分类
B+树索引,最常见的索引类型,大部分引擎都支持。
Hash索引
R-tree索引
full-text全文索引。通过建立倒排索引,快速匹配文档的方式,mysql 5.6之后支持全文索引。
B树
多路平衡查找树,n阶B树,是一个节点最多可以存储n-1个key,n个指针,即n个范围
B+树索引
所有的元素都出现在叶子节点,根节点作为索引范围,叶子节点之间形成一个单向链表

MySQL的B+树在原有基础上进行了优化,增加了一个指向相邻叶子节点的链表指针,形成了带有顺序的B+树,提高了区间的访问性能。即叶子节点是双向循环链表。
非叶子节点存储在一个块中

Hash索引
类似HashMap的实现。没有顺序。普通查询只需检索一次。
为什么InnoDB存储引擎选择使用B+树索引结构?
相对于二叉树,层级更少,搜索效率高
相对于B树,无论是叶子节点还是非叶子节点,都会保存数据,这样导致一页中存储的键值减少,指针跟着减少,保存同样的数据,只能增加树的高度,导致性能降低。
索引分类
主键索引,针对表中主键创建的索引,PRIMARY
唯一索引,避免同一个表中某数据列中的值重复,UNIQUE
常规索引。快速定位特定数据
全文索引。全为索引查找的数据为文本的关键词
InnoDB存储引擎中,根据索引的存储形式可以分为:
聚集索引,将数据存储和索引放到一起,索引结构的叶子节点保存了行数据。必须有,且只有一个
二级索引。将数据与索引分开存储,索引结构的叶子节点关联的是对应的主键。可以存在多个。
举个例子,主键为id,二级索引了属性name,查询name=xx时,首先查询name索引,然后得到id,拿到id查询聚集索引
然后得到数据,这叫回表查询。
聚集索引选取规则:
如果存在主键,主键索引就是聚集索引
如果不存在主键,将使用第一个唯一索引作为聚集索引
如果表没有主键,或没有合适的唯一索引,则InnoDB会自动生成一个rowid作为隐藏的聚集索引
索引语法
创建索引
如果只有一列,叫做单列索引,多列叫做组合索引
查看索引
删除索引
SQL性能分析
SQL执行频率

类似上述输出
慢查询日志
慢查询日志记录了所有执行时间超过指定参数(long_query_time,单位:秒,默认10s)的所有SQL语句的日志
MySQL的慢查询日志默认没有开启,需要在MySQL的配置文件(/etc/my.conf)中配置如下信息:
show_query_log=1
long_query_time=2
profile详情
查看当前会话下历史查询所消耗的时间
查看某个query各个阶段消耗的时间
explain执行计划
explain 或者 desc命令获取MySQL如何执行Select语句的信息,包括在Select语句执行过程中表如何连接和连接的顺序.
explain查询结果各字段意义
id,select查询的序列号,表示查询执行select子句或者是操作表的顺序(id相同,执行顺序从上到下;id不同,值越大,越先执行)。
select_type。
常见的有simple,primary,union,subquery
type
表示连接的类型,性能由好到差的连接类型为:Null,system、const、eq_ref、ref、range、index、all
尽量向前优化
possible_keys
可能用到的索引
key
实际使用的索引,如果为Null,则没有使用索引
key_len
表示索引中使用的字节数,该值为索引字段最大可能长度,并非实际使用长度,在不损失精确性的前提下,长度越短越好。
rows
MySQL任务必须要啊执行查询的行数,在innodb引擎表中,这是一个估计值,可能并不总是准确的
filtered
表示结果的行数占读取行数的百分比。
extra
额外字段
索引使用
最左前缀法则
如果索引了多列多列,要遵守最左前缀法则。最左前缀法则指的是查询从索引的最左列开始,并且不跳过索引中的列。
如果跳过某个列,索引将部分失效(后面的字段索引失效)
也即多列的索引,如果想要使用,必须将列全部都加上,否则会失效
索引失效
字符串不加单引号
索引将失效
模糊查询
如果仅仅是尾部模糊匹配,索引不会失效,如果是头部模糊匹配,索引会失效
or连接的条件
用or分割开的条件,如果or前的条件中的列有索引,而后面的列中没有索引,那么涉及的索引都不会被用到
数据分布影响
如果MySQL评估使用全局扫描更快,则不会使用索引
这个很智能。
函数
当我们在查询条件中对索引列做了计算、函数、类型转换操作,这些情况下都会造成索引失效
SQL提示
在SQL语句中加入一些人为的提示来达到优化操作的目的
use index,只是建议,但可能不会使用,会进行内部评估
ignore index,同上,忽略
force index,同上,强制,一定会有
覆盖索引
尽量使用覆盖索引(查询使用了索引,并且需要返回的列,在该索引中已经全部能够找到),减少select *
也即尽量明确查询结果的列名,并将其和索引中的列相同。这是为了尽量避免回表查询
对于主键索引来说,我们根据id查询,由于主键索引的叶子节点存储的全部数据,所以只需要一次
对于二级索引来说,叶子节点包括索引字段的值和主键id,那么这里如果查询的列不仅仅是索引的列,则会根据主键,去主键索引中查询,从而得到多余的列的数据。这样就多了一次查询索引。
前缀索引
当字段类型为字符串(varchar,text等时),有时候会需要索引很长的字符串,这让索引变得很大,查询时,浪费大量的磁盘IO,影响查询效率。此时可以只将字符串的一部分前缀,建立索引,这样可以大大节约索引空间,从而提高索引效率。
其中的n即为前缀长度。
n的大小选择,统计数据的特征,来决定n。
单列索引和联合索引的选择
在业务场景中,如果存在多个查询条件,考虑针对查询字段建立索引时,建议建立联合索引,而非单列索引。
索引设计原则
针对数据量大,且查询比较频繁的表建立索引
针对常作为查询条件(where)、排序、分组操作的字段建立索引
尽量选择区分度高的列作为索引,尽量建立唯一索引,区分度越高,使用索引的效率越高
如果时字符串类型,字段的长度较长,可以针对字段的特点,建立前缀索引
尽量使用联合索引,减少单列索引,查询时,联合索引很多时候可以覆盖索引,节省空间,避免徽标,提高查询效率
要控制索引数量,并不是多多益善,索引越多,维护代价越大
如果索引列不能存储null值,请在建表时使用not null约束。这样可以在查询时,让mysql更好的选择索引
最后更新于
这有帮助吗?