【学习记录】关于数据库优化的几点知识以及事务和锁

上午实习导师潇哥考核了下业务知识,然后说给你们讲下数据库这边的东西吧,然后balabala讲了挺多有用的。


下午把上午学到的梳理了下,包括查了一些资料,就整理了一篇文章出来。


数据库的基本优化

首先,数据库优化的最基本规则有两点

1.减少IO次数。

2.减少计算次数。(如果某查询会常用到而且计算次数较多的话,应当放在一张表中以减少计算)


然后是索引,众所周知索引是提高查找效率的。

但是当查询结果的字段数量占表中所有字段数比重越多的时候,索引与全表扫描查找的效率差值就越来越小,当到达一个阈值,索引的效率甚至会低于全表扫描,这个阈值一般会在5%左右,也就是查询结果数量占全表的5%以下时,用索引的效率是很高的。

但是在现在这个规则不是很适用了,因为现在的数据库中添加了一个叫做CBO(Cost Based Optimizer)的机制,会自动选择更适合的执行方式(走索引还是全表扫描)。


然后是join,关系型数据库之所以可以被称所关系型数据库的关键。

自然链接:join:链接的两个表都会显示,若无数据则显示空

左链接:left join:链接以左边表为准,左边表有数据才会显示此条目

右链接:right join:类比左链接,作用相反。


对join的优化,主要也是最基本的,就是调换join的顺序

1.若表a和表b均为1000w级别的表,c为1w级别的表,那么 a join b join c where xx = xx 这条语句查找数量级为1000w*1000w 以及1000w * 1w,而将顺序换为a join c join b where xx = xx 后,数量及变为了1000w*1w和1w*1000w,数量级显著降低了三个层级。

2.尽量避免无索引的大表(如两个大表join后的结果集)去join另一个表(无论此表有无索引),因为这会很慢。

解决办法:hash join。这个是在oracle中内置的一中join方法,可以解决上面这种问题,原理是将两个表先hash再join。现在定制的mysql也可以使用该方法。


索引工作模式图


索引有B+tree索引、bitmap索引(仅oracle有)、reverse索引(翻转索引)等,最常用的是B+tree索引。

B+tree索引

bitmap索引

reverse索引

下图是一个简单的B+tree索引示意图(图引B+树索引—水墨江南):



事务和锁

之前浅薄的接触过事务,事务级别(或者称为事务隔离级别)主要分为四级:Read Uncommitted(读取未提交内容)、Read Committed(读取提交内容)、Repeatable Read(可重读)、Serializable(可串行化),四级隔离程度依次升高。



脏读(Drity Read)
某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。

不可重复读(Non-repeatable read)
在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。

幻读(Phantom Read)
在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。


事务两种方式,这个我整理了下感觉总结的不好,直接引用一篇文章的原话(文引: mysql-事务处理):

MYSQL的事务处理主要有两种方法。

1、用begin,rollback,commit来实现
begin 开始一个事务
rollback 事务回滚
commit 事务确认

2、直接用set来改变mysql的自动提交模式
MYSQL默认是自动提交的,也就是你提交一个QUERY,它就直接执行!我们可以通过
set autocommit=0 禁止自动提交
set autocommit=1 开启自动提交
来实现事务的处理。
但注意当你用 set autocommit=0 的时候,你以后所有的SQL都将做为事务处理,直到你用commit确认或rollback结束,注意当你结束这个事务的同时也开启了个新的事务!按第一种方法只将当前的作为一个事务!
个人推荐使用第一种方法!
MYSQL中只有INNODB和BDB类型的数据表才能支持事务处理!其他的类型是不支持的!(切记!)


这次实习时候用的也是第一种事务方式,感觉也比较好使。

说一下锁。

mysql中支持 显式锁和隐式锁

InnoDB在开启事务时,获取隐式锁,在事务提交或者回滚时释放锁,InnoDB根据隔离级别自动处理锁。(文引: 高性能MySql学习笔记

——————————先整理到这,歇会继续整理————————————

——————————休息完毕,开始更新————————————

显式锁分两种:

乐观锁与悲观锁

简单来说,悲观锁是依赖数据库本身带的锁机制实现的,比如select * from t_table where xx = xx for update;

而乐观锁的实现机制并不依赖于数据库本身的锁,而是用版本(version)管理实现。
例:一条数据 
namebalanceversion
pandadru$10000

管理员A对该记录的balance进行操作:update t_table set balance=950 where name = pandadru version = 1 并提交。
管理员B此时也对该字段进行修改,update t_table set balance=950 where name = pandadru version = 1 并提交,因为乐观锁机制只允许version大于当前字段的内容提交,所以管理员B的提交失败。

以上只是个小例子,《 悲观锁和乐观锁》这篇文章对悲观锁和乐观锁讲得比较详细。


参考资料

孙佳潇的讲座(主要)





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值