咱们天天都在访问各类⽹站、APP,如微信、QQ、抖⾳、今⽇头条、腾讯新闻等,这些 东西上⾯都存在⼤量的信息,这些信息都须要有地⽅存储,存储在哪呢?数据库。mysql
因此若是咱们须要开发⼀个⽹站、app,数据库咱们必须掌握的技术,常⽤的数据库有 mysql、oracle、sqlserver、db2等。sql
上⾯介绍的⼏个数据库,oracle性能排名第⼀,服务也是至关到位的,可是收费也是⾮常 ⾼的,⾦融公司对数据库稳定性要求⽐较⾼,⼀般会选择oracle。数据库
mysql是免费的,其余⼏个⽬前暂时收费的,mysql在互联⽹公司使⽤率也是排名第⼀, 资料也⾮常完善,社区也⾮常活跃,因此咱们主要学习mysql。数组
篇幅所限,本文只详写了MySQL索引,须要的同窗可自行领取完整版MySQL学习笔记微信
1、什么是索引?索引就比如字典的目录同样 咱们一般都会先去目录查找关键偏旁或者字母再去查找 要比直接翻查字典查询要快不少数据结构
然而咱们在使用mysql数据库的时候也像字典同样有索引的状况下去查询,确定速度要快不少架构
2.1问题:oracle
磁盘app
IOide
磁盘预读
局部性原理:数据和程序都有汇集成群的倾向,同时以前被访问过的数据极可能再次被查询,空间局部性,时间局部性
磁盘预读:内存和磁盘发生数据交互的时候,通常状况下有一个最小的逻辑单元,页。 页通常由操做系统以为大小,4k或8k,而咱们在进行数据交互的时候,能够取页的整数倍来读取。
关注公众号:北游学Java 便可获取一份578页PDF文档的MySQL学习笔记
innodb存储引擎每次读取数据,读取16k
磁盘,查询数据的时候会优先将索引加载到内存中
key:实际数据行中存储的值
文件地址
offset:偏移量
key-values
哈希表,树(二叉树、红黑树、AVL树、B树、B+树)
OLAP:联机分析处理----对海量历史数据进行分析,产生决策性的策略----数据仓库—Hive
OLTP:联机事务处理----要求很短时效内返回对应的结果----数据库—关系型数据库(mysql、oracle)
3、mysql的索引数据结构HashMap数组加链表的结构,不适合做为索引的缘由:
1.哈希冲突会形成数据散列不均匀,会产生大量的线性查询,比较浪费时间
2.不支持范围查询,当进行范围查询的时候,必须挨个遍历
3.对于内存空间的要求比较高
优势: 若是是等值查询,很是快
在mysql中有没有hash索引?
1.memory存储引擎使用的是hash索引
2.innodb支持自适应hash
create table test(id int primary key,name varchar(30)) engine='innodb/memory/myisam' -- 5.1以后默认innodb复制代码
树这种数据结构有不少,咱们常见的有: 二叉树、BST、AVL、红黑树、B树、B+树
①二叉树:无序插入
这就是咱们的树的结构图,可是二叉树的数据插入是无序的,也就是说当须要查找的时候,仍是得一个一个挨着去遍历查找
②BST(二叉搜索树): 插入的数据有序,左子树必须小于根节点,右子树必须大于根节点--------使用二分查找来提升效率
这样的话若是要查询数据,能够经过二分查找,快速缩小范围,减小了时间复杂度 **可是若是插入的顺序是升序或者降序的话,树的形状会变成以下:
此时二叉搜索树就会退化成链表,时间复杂度又会变成O(n)
③AVL:平衡二叉树 为了解决上述问题,经过左旋转或右旋转让树平衡 最短子树跟最长子树高度只差不能超过1
由图咱们能够看到,当顺序插入的时候,会自动的进行旋转,以达到平衡 可是会经过插入性能的损失来弥补查询性能的提高 当咱们插入的数据不少时候,而查询不多的时候,因为插入数据会旋转一样会消耗不少时间
④红黑树(解决了读写请求同样多) 一样是通过左右旋让树平衡起来,还要变色的行为 最长子树只要不超过最短子树的两倍便可
查询性能和插入性能近似取得平衡 可是随着数据的插入、发现树的深度会变深,树的深度会愈来愈深,意味着IO次数越多,影响数据读取的效率
⑤ B树 为了解决上述数据插入过多,树深度变深的问题,咱们采用B树 把原来的有序二叉树变成有序多叉树
举例: 若是要查询select * from table where id=14?
问题1: B树不支持范围查询的快速查找,若是咱们查询一个范围的数据,查找到范围一个边界时,须要回到根节点从新遍历查找,须要从根节点进行屡次遍历,即使找到范围的另外一个边界,查询效率会下降。问题2: 若是data存储的是行记录,行的大小随着列数的增多,所占空间会变大。这时,一个页中可存储的数据量就会变少,树相应就会变高,磁盘IO次数就会变大。 思考2:三层B树可以存储多少条记录?答: 假设一个data为1k,innodb存储引擎一次读取数据为16k,三层即161616=4096; 可是每每在开发中,一个表的数据要远远大于4096,难道要继续加层,这样岂不就加大了IO
4、为何使用B+树?实际存储表数据的时候,怎么存储呢? key 完整的数据行 改造B+树
B+树对B树进行了改进,把数据全放在了叶子节点中,叶子节点之间使用双向指针链接,最底层的叶子节点造成了一个双向有序链表。例如: 查询范围 select * from table where id between 11 and 35?
对比B树和B+树?
叶子节点中才放数据
非叶子节点中不存储数据
B+树每一个节点包含更多个节点,这样作的好处,能够下降树的高度,同时将数据范围变成多个区间,区间越多查询越快
问题: 建立索引时用int仍是varchar?
答:视状况而定,可是记住必定让key越小越好
5、索引的建立在建立索引以前,我先说一下存储引擎 存储引擎: 表示不一样的数据在磁盘的不一样表现形式 你们去观察mysql的磁盘文件会发现 innodb: innodb的数据和索引都存储在一个文件下.idb myisam: myisam的索引存储在.MYI文件中,数据存储在.MYD中
概念:判断是不是聚簇索引就看数据和索引是否在一个文件中 innodb:
myisam: 非聚簇索引
MySQL—innodb----B+树 索引和数据存储在一块儿,找到索引便可读取对应的数据
MySQL—myisam----B+树 索引和存储数据的地址在一块儿,找到索引获得地址值,再经过地址找到对应的数据
接下来,我会建立一张案例表给你们展现
CREATE TABLE user_test( id INT PRIMARY KEY AUTO_INCREMENT,-- id为主键 uname VARCHAR(20) , age INT, gender VARCHAR(10), KEY `idx_uname` (`uname`) -- 索引选择为名字 )ENGINE = INNODB; INSERT INTO user_test VALUES(1,'张三',18,'男'); INSERT INTO user_test VALUES(NULL,'马冬梅',19,'女'); INSERT INTO user_test VALUES(NULL,'赵四',18,'男'); INSERT INTO user_test VALUES(NULL,'王老七',22,'男'); INSERT INTO user_test VALUES(NULL,'刘燕',16,'女'); INSERT INTO user_test VALUES(NULL,'万宝',26,'男');复制代码
select * from user_test where uname = '张三'; -- 当咱们表中有主键索引的时候,咱们再去设置一个uname为索引,那么此时这条sql语句的查询过程应该以下:复制代码
首先先根据uname查询到id,再根据id查询到行的信息 这样的操做走了两棵B+树,就是回表 当根据普通索引查询到聚簇索引的key值以后,再根据key值在聚簇索引中获取数据 咱们能够发现这样的操做是很浪费时间的,所以咱们平常操做的时候,尽可能减小回表的次数
select id,uname from table where uname = '张三'; -- 根据uname 能够直接查询到id,uname两个列的值,直接返回便可 -- 不须要从聚簇索引查询任何数据,此时叫作索引覆盖复制代码
在说最左匹配以前,咱们先聊一下几个名词 主键(通常为一个列)-------->联合主键(多个列) 索引-------->联合索引(可能包含多个索引列)
-- 假设有一张表,有id,name,age,gender四个字段,id是主键,name,age是组合索引列 -- 组合索引使用的时候必须先匹配name,而后匹配age select * from table where name = ? and age = ? ;-- 生效 select * from table where name = ?;-- 生效 select * from table where age = ? ;-- 不生效 select * from table where age = ? and name = ? ;-- 生效 --在mysql内部有优化器会调整对应的顺序复制代码
mysql5.7以后,默认支持的一个特色 举一个例子:
select * from table where name = ? and age = ? ; -- mysql里的三层架构: -- 客户端:JDBC -- 服务端:server -- 存储引擎:数据存储 在没有索引下推以前,根据name从存储引擎中获取符合规则的数据,在server层对age进行过滤 有索引下推以后,根据name、age两个条件从存储引擎中获取对应的数据复制代码
分析:有索引下推的好处,若是咱们有50条数据,咱们经过过滤会获得10条数据,若是没有索引下推,会先获取50条再去排除获得10条,而有了下推以后,咱们会直接在存储引擎就过滤成了10条