索引
前置内容
B树以作者R.Bayer命名 B+树使其改进
B-树
基本内容
这是一颗二叉排序树,平衡二叉树,那么B树是平衡二叉树的扩展,即可以是多叉的,有多个关键字就会有多个分支,如下图
标准B树:
+ 每个节点至多有m个分支,而最少分支数要看是否为根节点,若是根节点且不是叶子节点则至少有2个分支,非根非叶节点至少有
⌈
m
/
2
⌉
\lceil m/2 \rceil
⌈m/2⌉个分支,上图为5阶B树,47|48|52|59 4个数字将区间划分为5段(B树的阶数是人为规定的不以当前B树的情况而变化,可以理解为每个节点都是相同大小的数组存放的)
+ 有n(k<=n<=m)个节点的分支的节点有n-1个关键字,他们按递增顺序排序,k=2(根节点)或者
⌈
m
/
2
⌉
\lceil m/2 \rceil
⌈m/2⌉(非根节点)
+ 节点内关键字互不相等
+ 叶子节点处于同一层;可以用空指针表示,即查找失败达到的位置
+ pi所指向的节点关键字小于Keyi+1大于Keyi
B树结构体:
两个数组:第一个n:有多少个关键字,后边有n个关键字
第二行:一排指针,指向当前节点的孩子节点的指针(n+1个指针,代表了n个关键字划分的n+1个区域)
操作
- 关键字查找
从根节点开始从左往右扫描节点中的关键字,如果找不到,就沿着适当的分支到下一层寻找- 查找成功
- 查找失败:查到空指针
- 关键字插入
- 关键字删除
B+树
+ 在B+树种,具有n个关键字的节点含有n个分支,而在B树中有n个关键字的节点含有n+1个分支
+ 在B+树中,每个节点(除根节点外)中的关键字个数n的取值范围是$\lceil m/2 \rceil$<= n <=m,根节点的取值范围是2<=n<=m;
+ 在B+树中叶子节点包含信息,并且包含了全部关键字,叶子节点引出的指针指向记录
+ 在B+树种所有的非叶子节点仅仅起到一个索引的作用,也就是说节点中的每个索引项只是含有对应子树的最大关键字和指向该子树的指针,不含该关键字对应记录的储存地址,而在B树种每个关键字对应于一个记录的存放地址
+ 在B+树中有一个指针指向关键字最小的叶子节点,所有的叶子节点连接成为一个线性链表,而B树没有
B树学习链接:https://www.bilibili.com/video/BV1Aa4y1j7a4?from=search&seid=16991788897191899745
索引的基本原理
概述
索引是一种帮助mysql高效查询数据的数据结构,
索引用于快速的寻找具有特定值的记录,如果没有索引,一般来说执行的时候需要遍历整张表。
- 索引的原理:把无序的数据变成有序的查询
- 把创建了索引的列的内容进行排序
- 对排序结果生成倒排表
- 在倒排表内容上拼接上数据地址链
- 在查询的时候,先拿到倒排表内容,再取出数据地址链,从而拿到数据
对于没有建立索引的左侧表,需要从上往下依次查询(慢)
建立了索引的表结构(简单理解为二叉树),索引以某种方式指向数据
索引优劣势
- 优势:
- 类似于书籍的目录索引,提高检索的效率,降低IO的成本
- 通过索引对数据进行排序,降低数据排序的成本,降低CPU的消耗
- 劣势
- 索引实际上也是一张表,表中存了主键和索引字段,并指向实体类记录,索引也要占用磁盘空间
- 虽然可以提高效率,但是却降低了更新表的效率,不仅要更新表,调整索引
索引结构
索引在mysql中的存储引擎层实现,不在服务层实现每种存储引擎可以不完全一样,也不是有的储存引擎都支持索引类型,目前提供了四种
- BTREE索引:最常见的索引类型,大部分的索引都支持B树索引,innondb就是使用这个(实际上用的B+树,多路平衡搜索树)
- HASH索引:只支持Memory引擎,使用场景简单
- R-tree索引(空间索引)
- Full-text索引:全文索引,用于全文检索
- 在mysql中索引使用了改进的B+树,也就是在原有的B+树的基础上,增加一个指向相邻叶子节点的链表指针,就形成了带有顺序指针的B+树,提高了区间访问的性能。
索引分类
索引语法
准备环境
CREATE DATABASE demo_01 DEFAULT CHARSET = utf8mb4
USE demo_01
CREATE TABLE `city` (
`city_id` INT ( 11 ) NOT NULL AUTO_INCREMENT,
`city_name` VARCHAR ( 50 ) NOT NULL,
`country_id` INT ( 11 ) NOT NULL,
PRIMARY KEY ( `city_id` )
) ENGINE = INNODB DEFAULT CHARSET = utf8;
CREATE TABLE `country` (
`country_id` INT ( 11 ) NOT NULL AUTO_INCREMENT,
`country_name` VARCHAR ( 100 ) NOT NULL,
PRIMARY KEY ( `country_id` )
) ENGINE = INNODB DEFAULT CHARSET = utf8;
INSERT INTO `city` (`city_id`,`city_name`,`country_id`) values(1,'西安',1);
INSERT INTO `city` (`city_id`,`city_name`,`country_id`) values(2,'NewYork',2);
INSERT INTO `city` (`city_id`,`city_name`,`country_id`) values(3,'北京',1);
INSERT INTO `city` (`city_id`,`city_name`,`country_id`) values(4,'上海',1);
INSERT INTO `country` (`country_id`,`country_name`) values(1,'China');
INSERT INTO `country` (`country_id`,`country_name`) values(2,'America');
INSERT INTO `country` (`country_id`,`country_name`) values(3,'Japan');
INSERT INTO `country` (`country_id`,`country_name`) values(4,'UK');
索引语法
-
在mysql中对主键默认有主键索引
-
CREATE index idx_city_name on city(city_name);
-
查看索引
show index from city;
- 默认都是B+树
-
删除索引
drop index idx_city_name on city;
-
修改索引
索引设计原则
视图
概述
- 视图(View)是一种虚拟存在的表。视图并不在数据库中实际存在,行和列数据来自定义视图的查询中使用的表,并且是在使用视图时动态生成的。通俗的讲,视图就是一条SELECT语句执行后返回的结果集。所以我们在创建视图的时候,主要的工作就落在创建这条SQL查询语句上。
视图相对于普通的表的优势主要包括以下几项。
- 简单:使用视图的用户完全不需要关心后面对应的表的结构、关联条件和筛选条件,对用户来说已经是过滤好的复合条件的结果集。
- 安全:使用视图的用户只能访问他们被允许查询的结果集,对表的权限管理并不能限制到某个行某个列,但是通过视图就可以简单的实现。
- 数据独立:一旦视图的结构确定了,可以屏蔽表结构变化对用户的影响,源表增加列对视图没有影响;源表修改列名,则可以通过修改视图来解决,不会造成对访问者的影响。