研磨Mysql之索引

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,表明索引用来读取数据而非查找。

发布了59 篇原创文章 · 获赞 2 · 访问量 2075

猜你喜欢

转载自blog.csdn.net/zuodaoyong/article/details/102019977