MyISAM 存储引擎索引实现: MyISAM 索引文件(磁盘上表对应.MYI)和数据文件(MYD)是分离的(非聚集)
InnoDB 存储引擎索引实现: InnoDB 索引实现(聚集)
- 表数据文件本身就是B+Treee 组织的一个索引结构文件
- 聚集索引-叶子节点包含了完整的数据记录
- 为什么建议INnoDB表必须建主键,并且推荐推荐使用整形的自增主键? 如果没有建立主键,数据会帮找一列(唯一索引)如果没有则默认给加一个类似自增的主键。【,存储空间,比较性能整形效率高,自增的会一直往后面加,不会分裂或者说调整数】
- 为什么非主键索引结构叶子节点存储的是主键值?(一致性和节省存储空间)
问:为什么InnoDB表必须有主键。并且推荐使用整型的自增主键:
1、如果设置了主键,那么InnoDB会选择主键作为聚集索引、如果没有显式定义主键,则InnoDB会选择第一个不包含有NULL值的唯一索引作为主键索引、如果也没有这样的唯一索引,则InnoDB会选择内置6字节长的ROWID作为隐含的聚集索引(ROWID随着行记录的写入而主键递增)。
2、如果表使用自增主键
那么每次插入新的记录,记录就会顺序添加到当前索引节点的后续位置,主键的顺序按照数据记录的插入顺序排列,自动有序。当一页写满,就会自动开辟一个新的页
3、如果使用非自增主键(如果身份证号或学号等)
由于每次插入主键的值近似于随机,因此每次新纪录都要被插到现有索引页得中间某个位置,此时MySQL不得不为了将新记录插到合适位置而移动数据,甚至目标页面可能已经被回写到磁盘上而从缓存中清掉,此时又要从磁盘上读回来,这增加了很多开销,同时频繁的移动、分页操作造成了大量的碎片,得到了不够紧凑的索引结构,后续不得不通过OPTIMIZE TABLE来重建表并优化填充页面。
问:为什么非主键索引结构叶子结点存储的是主键值:
减少了出现行移动或者数据页分裂时二级索引的维护工作(当数据需要更新的时候,二级索引不需要修改,只需要修改聚簇索引,一个表只能有一个聚簇索引,其他的都是二级索引,这样只需要修改聚簇索引就可以了,不需要重新构建二级索引)
聚簇索引也称为主键索引,其索引树的叶子节点中存的是整行数据,表中行的物理顺序与键值的逻辑(索引)顺序相同。一个表只能包含一个聚集索引。因为索引(目录)只能按照一种方法进行排序。
非聚簇索引(普通索引)的叶子节点内容是主键的值。在 InnoDB 里,非主键索引也被称为二级索引(secondary index)。
存储引擎是针对表的,而不是对数据库的。
B-Tree : 1.没有双向指针,不能支持范围查找; 2. 非叶子节点存储data,相同高度的数据, 一个分页节点大小16k; 所以横向存储数据就变少
B+Tree: 1.双向指针,支持范围查找;2. 非叶子节点没有存储data,相同高度的数据, 一个分页节点大小16k; 所以横向存储数据就变多
联合索引必须遵循最左匹配原则:
key: idx_name_age_position(name,age,position) using btree
1: select * from person where name=‘Bill’ and age=‘30’ 【使用索引】
2: select * from person where age=‘30’ and position=‘dev’ 【不使用索引,】
3: select * from person where position=‘dev’ 【不使用索引】
原理:
索引有序排列;
1条sql 因为底层存储先是 一级name 第二age 第三 position ; 因为索引是有序存储的;
2条sql 因为age并非一定顺序存储的,必须建立在一级name相同的前提下才会是age排序。否则age是无序的。
3条sql 因为position 并非一定顺序存储,必须建立在一级name和二级age相同的前提下,position才会是有序的。
页
一页数据总大小16KB
在插入数据的时候,用户数据区就按照主键排序进行插入。虽然会影响插入的效率。但是是为了后续的查询效率;由于用户数据区使用的链表方式存储,链表的优点是插入快查询慢。因为如果查询需要从头到尾顺序进行查找; 所以为了提高查询效率又设计了页目录的方式。 使用数组存储方式,查询快:页面中存储最小索引数据+最小索引数据指针地址(为了方便快速定位数据) ;例如:select * from t1 where a = 30 的时候,首先使用二分查找发进行查询页目录,找到对应的页目录通过指针进行查找用户数据区域数据进行查找;
主键索引
如果查找7,先是从根节点从上往下找,然后再从最左叶子节点开始进行查找的方式是全表扫描,1->3->5->7;
如果是从根节点从上往下找, 根节点[1,5]->[5,7]->[7455g] 的方式,则是走索引
组合索引: 必须遵守最左匹配原则
explain select * from t1 where b>1 – 可以走索引但是,通过索引走完之后,又需要把组合索引下面大于1 所有主键通过回表方式去找对应的数据。这样效率就比走全部扫描更加慢了;所以优先走全部扫描了;
explain select b,c,d from t1 where b>1; 走了索引,因为指定了指定正好是索引字段
explain select a,b,c,d from t1 where b>1; 走了索引,因为指定了指定正好是索引字段
explain select * from t1 where b>6 又走了索引,
explain select b from t1 走索引扫描,因为索引字段存储是不整的数据,叶子节点存的记录行数比主键索引的叶子节点记录全部数据行数要多。它的页就更加少。查询更加快些
explain select a,b,c,d from t1 order by b,c,d; 走索引,因为组合索引已经有所有数据;
explain select * from t1 order by b,c,d; 第一种方案:不走索引,因为不单独排序是走索引,但是还有其他数据在不在组合索引树上,还需要回表;
第二种方案:全表扫描+排序
explain select * from t1 where e=1; 不走索引
explain select * from t1 where e=‘1’; 走索引;
explain select * from t1 where a=1; 走索引
explain select * from t1 where a=‘1’; 不走索引
mysql 如果数据类型转换,非数字字符全部为0