将无序的数据变成相对有序的数据(就像查有目的一样)
在经常需要搜索的列上,可以加快搜索的速度;
在经常使用在where子句中的列上面创建索引,加快条件的判断速度。
将打算加索引的列设置为NOT NULL,否则将导致引擎放弃使用索引而进行全表扫描
在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间
避免where子句中对字段施加函数,这会造成无法命中索引
在中到大型表索引都是非常有效的,但是特大型表的维护开销会很大,不适合建索引,建立用逻辑索引
在经常用到连续的列上,这些列主要是由一些外键,可以加快连接的速度
与业务无关时多使用逻辑主键,也就是自增主键在使用InnoDB时使用与业务无关的自增主键作为主键,即使用逻辑主键,而不要使用业务主键。
删除长期未使用的索引,不用的索引的存在会造成不必要的性能损耗
在使用limit offset查询缓存时,可以借助索引来提高性能。
不可以。因为这样会形成一个有序数组,文件系统和数据库的索引都是存在硬盘上的,并且如果数据量大的话,不一定能一次性加载到内存中。有序数组没法一次性加载进内存,这时候B+树的多路存储威力就出来了,可以每次加载B+树的一个结点,然后一步步往下找,
表锁
不会出现死锁,发生锁冲突几率高,并发低。
MyISAM在执行查询语句(select)前,会自动给涉及的所有表加读锁,在执行增删改操作前,会自动给涉及的表加写锁。
MySQL的表级锁有两种模式:表共享读锁和表独占写锁。
读锁会阻塞写,写锁会阻塞读和写
MyISAM不适合做写为主表的引擎,因为写锁后,其它线程不能做任何操作,大量的更新会使查询很难得到锁,从而造成永远阻塞。
行锁
会出现死锁,发生锁冲突几率低,并发高。
在MySQL的InnoDB引擎支持行锁,与Oracle不同,MySQL的行锁是通过索引加载的,也就是说,行锁是加在索引响应的行上的,要是对应的SQL语句没有走索引,则会全表扫描,行锁则无法实现,取而代之的是表锁,此时其它事务无法对当前表进行更新或插入操作。
行锁的实现需要注意:
行锁的适用场景:
A用户消费,service层先查询该用户的账户余额,若余额足够,则进行后续的扣款操作;这种情况查询的时候应该对该记录进行加锁。
否则,B用户在A用户查询后消费前先一步将A用户账号上的钱转走,而此时A用户已经进行了用户余额是否足够的判断,则可能会出现余额已经不足但却扣款成功的情况。
为了避免此情况,需要在A用户操作该记录的时候进行for update加锁
内连接:只有两个元素表相匹配的才能在结果集中显示。 外连接: 左外连接: 左边为驱动表,驱动表的数据全部显示,匹配表的不匹配的不会显示。 右外连接:右边为驱动表,驱动表的数据全部显示,匹配表的不匹配的不会显示。 全外连接:连接的表中不匹配的数据全部会显示出来。 交叉连接: 笛卡尔效应,显示的结果是链接表数的乘积。
拆分其实又分垂直拆分和水平拆分
案例: 简单购物系统暂设涉及如下表:
1.产品表(数据量10w,稳定)
2.订单表(数据量200w,且有增长趋势)
3.用户表 (数据量100w,且有增长趋势)
以 MySQL 为例讲述下水平拆分和垂直拆分,MySQL能容忍的数量级在百万静态数据可以到千万
垂直拆分
解决问题:表与表之间的io竞争
不解决问题:单表中数据量增长出现的压力
方案: 把产品表和用户表放到一个server上 订单表单独放到一个server上
水平拆分
解决问题:单表中数据量增长出现的压力
不解决问题:表与表之间的io争夺
方案:用户表 通过性别拆分为男用户表和女用户表,订单表 通过已完成和完成中拆分为已完成订单和未完成订单,产品表 未完成订单放一个server上,已完成订单表盒男用户表放一个server上,女用户表放一个server上(女的爱购物 哈哈)。
我们在MySQL中的数据一般是放在磁盘中的,读取数据的时候肯定会有访问磁盘的操作,磁盘中有两个机械运动的部分,分别是盘片旋转和磁臂移动。盘片旋转就是我们市面上所提到的多少转每分钟,而磁盘移动则是在盘片旋转到指定位置以后,移动磁臂后开始进行数据的读写。那么这就存在一个定位到磁盘中的块的过程,而定位是磁盘的存取中花费时间比较大的一块,毕竟机械运动花费的时候要远远大于电子运动的时间。当大规模数据存储到磁盘中的时候,显然定位是一个非常花费时间的过程,但是我们可以通过B树进行优化,提高磁盘读取时定位的效率。
为什么B类树可以进行优化呢?我们可以根据B类树的特点,构造一个多阶的B类树,然后在尽量多的在结点上存储相关的信息,保证层数(树的高度)尽量的少,以便后面我们可以更快的找到信息,磁盘的I/O操作也少一些,而且B类树是平衡树,每个结点到叶子结点的高度都是相同,这也保证了每个查询是稳定的。
特别地:只有B-树和B+树,这里的B-树是叫B树,不是B减树,没有B减树的说法。
MySQL中存储索引用到的数据结构是B+树,B+树的查询时间跟树的高度有关,是log(n),如果用hash存储,那么查询时间是O(1)。
采用Hash来存储确实要更快,但是采用B+树来存储索引的原因主要有以下两点:
一、从内存角度上说,数据库中的索引一般是在磁盘上,数据量大的情况可能无法一次性装入内存,B+树的设计可以允许数据分批加载。
二、从业务场景上说,如果只选择一个数据那确实是hash更快,但是数据库中经常会选中多条,这时候由于B+树索引有序,并且又有链表相连,它的查询效率比hash就快很多了。
ACID,原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)
我们以从A账户转账50元到B账户为例进行说明一下ACID这四大特性。
原子性
原子性是指一个事务是一个不可分割的工作单位,其中的操作要么都做,要么都不做。即要么转账成功,要么转账失败,是不存在中间的状态!
如果无法保证原子性会怎么样?
OK,就会出现数据不一致的情形,A账户减去50元,而B账户增加50元操作失败。系统将无故丢失50元~
一致性
一致性是指事务执行前后,数据处于一种合法的状态,这种状态是语义上的而不是语法上的。 那什么是合法的数据状态呢?这个状态是满足预定的约束就叫做合法的状态,再通俗一点,这状态是由你自己来定义的。满足这个状态,数据就是一致的,不满足这个状态,数据就是不一致的!
如果无法保证一致性会怎么样?
隔离性
隔离性是指多个事务并发执行的时候,事务内部的操作与其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
如果无法保证隔离性会怎么样?
假设A账户有200元,B账户0元。A账户往B账户转账两次,金额为50元,分别在两个事务中执行。如果无法保证隔离性,A可能就会出现扣款两次的情形,而B只加款一次,凭空消失了50元,依然出现了数据不一致的情形!
持久性
根据定义,持久性是指事务一旦提交,它对数据库的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
如果无法保证持久性会怎么样?
在MySQL中,为了解决CPU和磁盘速度不一致问题,MySQL是将磁盘上的数据加载到内存,对内存进行操作,然后再回写磁盘。好,假设此时宕机了,在内存中修改的数据全部丢失了,持久性就无法保证。
设想一下,系统提示你转账成功。但是你发现金额没有发生任何改变,此时数据出现了不合法的数据状态,我们将这种状态认为是数据不一致的情形。
分为两个层面来说。
主要是利用 Innodb 的undo log。 undo log名为回滚日志,是实现原子性的关键,当事务回滚时能够撤销所有已经成功执行的 SQL语句,他需要记录你要回滚的相应日志信息。 例如
undo log记录了这些回滚需要的信息,当事务执行失败或调用了rollback,导致事务需要回滚,便可以利用undo log中的信息将数据回滚到修改之前的样子。
主要是利用Innodb的redo log。重写日志, 正如之前说的,MySQL是先把磁盘上的数据加载到内存中,在内存中对数据进行修改,再写回到磁盘上。如果此时突然宕机,内存中的数据就会丢失。 怎么解决这个问题? 简单啊,事务提交前直接把数据写入磁盘就行啊。 这么做有什么问题?
于是,决定采用redo log解决上面的问题。当做数据修改的时候,不仅在内存中操作,还会在redo log中记录这次操作。当事务提交的时候,会将redo log日志进行刷盘(redo log一部分在内存中,一部分在磁盘上)。当数据库宕机重启的时候,会将redo log中的内容恢复到数据库中,再根据undo log和binlog内容决定回滚数据还是提交数据。
采用redo log的好处?
其实好处就是将redo log进行刷盘比对数据页刷盘效率高,具体表现如下:
《高性能MySQL》:https://item.jd.com/11220393.md
《 MySQL是怎样运行的 从根儿上理解MySQL》:https://item.jd.com/13009316.md
《 MySQL技术内幕:InnoDB存储引擎(第2版)》:https://item.jd.com/11252326.md
极客时间专栏-《MySQL实战45讲》:https://time.geekbang.org/column/intro/100020801
https://blog.csdn.net/BEYOA/article/details/115829327
https://segmentfault.com/a/119000003984710
https://blog.csdn.net/FL63Zv96950w/article/details/11577443
https://segmentfault.com/a/1190000039848
https://blog.csdn.net/wypblog/article/details/1158432
https://segmentfault.com/q/101000003971
https://blog.csdn.net/wei6569/article/details/11585679
https://blog.csdn.net/dog250/article/details/115783
https://segmentfault.com/q/101000421003971
https://blog.csdn.net/prograer_editor/article/details/11572561
https://segmentfault.com/q/10100004134471
https://csdnnews.blog.csdn.net/article/details/11574389
https://segmentfault.com/q/101000714155354