1、索引定义
索引是帮助Mysql高效获取数据的数据结构,即排好序的快速查找数据结构。
在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法。
2、索引的优势和劣势
优势:(1)提高数据检索的效率,降低数据库的IO成本
(2)降低数据排序的成本,降低cpu的消耗
劣势:(1)索引是一张表,保存了主键与索引字段,并指向实体表的记录。所以索引列也是占用空间的。
(2)对表进行insert,update,delete时,会调整更新所带来的键值变化后的索引信息。
(3)如果表中数据是大数据量时,需要研究建立最优秀的索引,或者优化查询语句。
3、索引的分类
(1)单值索引:一个索引只包含单个列,一个表可以有多个单值索引
(2)唯一索引:索引列的值时唯一的,但允许为空
(3)复合索引:一个索引包含多列
4、索引结构
(1)BTree索引
SHOW GLOBAL STATUS LIKE 'innodb_page_size' 查看mysql一次性加载数据页的默认大小是16K
(2)mysql底层索引数据结构是B+树
特点:
(1)非叶子节点不存储data,只存储索引,目的是可以存放更多的索引
(2)叶子节点包含所有索引字段
(3)叶子节点用指针连接,提高区间访问的性能
假设索引里存储的索引类型是bingint,我们计算下,
对于非叶子节点,一个块是16K,存储一个索引需要14B,则,一个块可以存储的索引数=16k/14B=1170(个)
对于叶子节点,假设一个索引加上数据是1k,一个块16K,则该块可以存放索引数=16K/1K=16个
对于3层结构B+树,可以存放索引个数=1170*1170*16=21,902,400
(3)MYISAM索引文件和数据文件是分离(非聚集)
test表底层存储方式:frm是表结构数据,MYD是数据文件,MYI是索引文件
(4)Inno_DB索引(聚集)
聚集的定义:叶子节点包含了完整的数据记录
frm:表结构,ibd:存放数据和索引
考虑一个问题,为什么Inno_db存储引擎的表必须有主键?
原因是:主键的每一个叶子节点的一个索引存储着该行的其他字段,
如果没有建立主键,mysql会选取字段中有唯一值的字段作为主键,如果找不到,则mysql自己生成一个类似rowid的值作为主键,但是对于用户是不可见的
非主键索引的叶子节点存储的是主键值,不是该行的其他值
5、需要索引的场景
(1)主键自动建立唯一索引
(2)频繁作为查询条件的字段
(3)查询中与其他表关联的字段,外键关系建立索引
(4)在高并发下创建组合索引
(5)查询中排序的字段,排序字段建立索引后会提高排序性能
(6)查询中统计或者分组的字段
6、不需要索引的场景
(1)表记录太少
(2)经常增删改的字段
(3)字段包含重复内容,建立索引没有太大作用
7、Mysql性能瓶颈
(1)CPU:cpu在饱和的时候一般发生在数据装入内存或者磁盘上读取数据的时候
(2)IO:发生在装入数据远大于内存容量的时候
(3)sql:sql编写执行效率低下
8、Explain的使用
(1)id
select 查询的序列号,包含一组数字,表示查询中执行select子句或者操作表的顺序
1)id相同,执行顺序由上至下
2)id不同,如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行。
3)id相同不同,同时存在
(2)select_type
SIMPLE:简单的select查询,查询中不包含子查询或者UNION
PRIMARY:查询中若包含任何复杂的子部分,最外层查询则被标记为PRIMARY
SUBQUERY:在select或者where列表中包含子查询。
derived:在from列表中包含子查询被标记为derived(衍生),mysql会递归执行这些子查询,把结果放在临时表里。
union:若第二个select出现在union之后,则被标记为union,若union包含在from子句的子查询中,外层select将被标记为:derived。
union result:从union表获取结果的select
(3)type
值从好到差依次:system>const>eq_ref>ref>range>index>all
system:表只有一行记录,这是const类型的特例,平时不会出现。
const:通过索引一次找到,const用于比较primary key或者unique索引,因为只匹配一行数据,所有很快。如将主键置于where列表中,mysql将查询转换为一个常量。
eq_ref:唯一索引扫描,对于每个索引键表中只有一条记录与之匹配。常见于主键或者唯一索引扫描。
ref:非唯一性索引扫描,返回匹配某个单独值的所有行,它可能会找到多个符合条件的行,所以他应该属于查找和扫描的混合体。
range:只检索给定范围的行,使用一个索引来选择行。key列显示使用了哪个索引一般就是在where语句中出现between,<,>,in 等查询。这种范围查询比全表扫描好,因为开始于索引一点,结束索引另一点。
index:Full Index Scan,遍历所有索引树
all:全表扫描
(4)possible_keys:显示可能应用在这张表中的索引,一个或者多个。
(5)key:实际使用的索引,如果为null,则没有使用索引,查询中若使用了覆盖索引,则该索引仅出现在key列表中。
(6)ref:显示索引的哪一列被使用了,如果可能的话,是一个常数。
(7)rows:根据表统计的信息及索引选用情况,大致估算出找到所需的记录需要读取多少行。
(8)Extra:
1)Using filesort:说明mysql会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取。
mysql中无法利用索引完成的排序操作称为“文件排序”。
2)Using temporary:使用了临时表保存中间结果,mysql在对查询结果排序时使用临时表,常见排序order by和分组查询group by
3)Using Index:表示select操作中使用了覆盖索引,如果同时出现using where,表明索引被用来执行索引键值的查找。
如果没有同时出现using where,表明索引用来读取数据而非查找。