文章目录
重点
- 索引
- 事物
- 调优
- mvcc
- 存储引擎
- 主从复制
- 读写分离
- 分库分表
- 锁
- 日志系统
索引
红黑树和AVL树
二叉平衡树:二叉搜索树的一种,追求绝对平衡也就是任何一个左子树和右子树高度小于1
红黑树:二叉平衡树的一种,他不追求高度小于1
什么是索引
排好序的数据结构。
每个节点(磁盘块)可以存16K数据,mysql索引一般3到4层就足以支撑千万级别的表查询。所以创建索引的字段短一些好,这样每个节点就存储更多指针。
B树和B+树的区别
相同点:它是一种二叉平衡树的一个种类,可以使查找时间为二分查找,O(logN)。多叉平衡树,每个节点(磁盘块)存储多个数据让数更矮,每个节点可以存16K数据
- 存储内容:B树的每个结点都存储了key和data,B+树的data存储在叶子节点上。节点不存储data,这样一个节点就可以存储更多指针。可以使得树更矮。查找更快
- 查找速度:b+数的根节点存储的指针一般常驻内存,所以查找速度非常快
- 稳定性:b+树查询的数据都在最底层的叶子节点,因此b+树查找更稳定
- 范围查找:b+树最底层叶子树节是排好序的,并且每个字节点使用双向指针连接,范围查找很快
为何使用B/B+树而不使用hash索引
hash结构:hash算法(MD5,crc16等算法的统称),会在底层做一次hash运算,把hash运算结果和字段索引地址关联,使用哈希一次运算就可以通过我们的索引找到数据地址。那么我们使用哈希查找速度更快,但是实际使用中我们没有使用哈希。
原因: 范围查找,hash索引没法支持:B+树他最底层数据节点是双向指针,找到了某个值,然后直接向后查找,找到范围。
我们在创建表的时候用代理主键还是自然主键
代理主键:和数据无关的列
自然主键:和数据相关的列
比如身份证信息,我们可以用身份证号作为主键(自然主键),也可以再创建一个id号作为主键(代理主键)。那么我们用哪个好:
用id的话占用更小空间,身份证号占用空间太大。所以使用代理主键更好
为何索引主键设置自增
当我们新建一行数据,当插入索引时,因为我们叶子结点是有序双向链表,如果索引自增,那么我们直接后增加节点。
但是如果非自增,我们要保持有序,那么我们就往前插入节点,后面的节点分页结构就会变化。维护成本太高,性能就会降低。
聚簇索引和非聚簇索引
https://www.jianshu.com/p/fa8192853184
- 聚簇索引:索引和数据存储在一块。innodb的主键索就都是聚簇索引
- 非聚簇(稀疏)索引:索引和数据分开存储,由每个索引指向数据对应的位置。
非聚簇索引的两种形式:
-
myisam非聚簇索引:索引和数据分开。每个索引存储一个对应的数据空间的地址。每次先在索引中搜索对应索引,然后再去对应的数据存储地址空间查找数据。myisam的辅助索引也和主键索引查找方式一样。
-
innodb的二级索引(辅助索引,普通索引)也是非聚簇索引但他和myisam的非聚簇索引不同,他是需要二次查找的。因为二级索引叶子结点存放的是主键的值,所以需要根据根据索引做一次回表操作,查询到真实数据。也就是需要二次查找。所以他的查询效率要低于聚簇索引。但是他的维护成本要低一些,比如我要修改某个数据,我们不需要改动索引
二级索引举例:
比如我们一个数据表主键索引是id。然后我们的二级索引是name,当我们对name进行条件搜索的时候需要两步:第一步:在辅助索引的B+树种找到对应的主键索引也就是ID。第二步:再使用主键索引在主键索引B+树种查询到对应数据(回表)。
区别:
- 聚簇索引的索引指针和数据存储在一起,速度更快。而非聚簇索引需要二次查找速度更慢
- 聚簇索引维护成本高,当插入数据的时候,如果需要分页,也就是插入数据导致的不同节点块分开,这时必须移动对应的数据。而非聚簇索引只需要分割索引,数据不需要移动,因为有指针指向数据地址。
innodb相对于myisam区别
innodb和myisam都是形容数据库表的引擎。
- 索引:InnoDB(索引组织表)使用的(聚集)聚簇索引,通过主键索引效率很高。InnoDB必须要有主键索引,没有主键索引他无法生成索引数据表。 MyISAM(堆组织表)使用的是非聚簇(稀疏)索引。索引和数据分离。要重定位一次。
- MyISAM的索引和数据是分开的,并且索引是有压缩的。内存使用率就对应提高了不少。能加载更多索引,而Innodb是索引和数据是紧密捆绑的,没有使用压缩从而会造成Innodb比MyISAM体积庞大不小。
- 事物:innodb支持事物,myisam不支持,这是选择innodb很大的一个原因,因为一旦数据插入错误就回滚
- 锁 myisam只支持表级锁,而innodb支持行级锁,表锁
- 外键innodb支持外键,myisam不支持
什么是联合(复合)索引
你得知道最左前缀匹配原则,这个东西是跟联合索引(复合索引)相关联的,就是说,你很多时候不是对一个一个的字段分别搞一个一个的索引,而是针对几个索引建立一个联合索引的。
举个例子,你如果要对一个商品表按照店铺、商品、创建时间三个维度来查询,那么就可以创建一个联合索引:shop_id、product_id、gmt_create
所以你一般来说不是就建立3个索引,一般来说会针对平时要查询的几个字段,建立一个联合索引
后面在java系统里写的SQL,都必须符合最左前缀匹配原则,确保你所有的sql都可以使用上这个联合索引,通过索引来查询
最左前缀匹配原则:对于复合索引Mysql从左到右的使用索引中的字段,一个查询可以只使用索引中的一部份但只能是最左侧部分
create index (shop_id,product_id,gmt_create)
一个索引包含个字段,
那么mysql的比较字段顺序,先比较第一个字段,然后第二个字段,然后第三个字段。
如果您知 道姓,电话簿将非常有用;
如果您知道姓和名,电话簿则更为有用,
但如果您只知道名不姓,电话簿将没有用处。
所以说创建复合索引时,应该仔细考虑列的顺序。
设计索引原则
- 尽量使用唯一索引。区分度越高,索引效率越高。例如,学生表中学号是具有唯一性的字段。为该字段建立唯一性索引可以很快的确定某个学生的信息。
- 对于经常需要查询的字段建立索引,数据量大的表进行建立索引
- 对于经常需要排序的字段建立索引,因为索引本身就是有序的
- 尽可能使用短索引,因为每个磁盘块大小固定为16K,使用短索引,则每块可以存储更多的索引数据
- 限制索引的数目,并及时清理不需要的索引,因为索引也要占用空间,索引越多,更新表速度越慢