数据库

三大范式:

第一范式就是属性不可分割,每个字段都应该是不可再拆分的。
第二范式就是要求表中要有主键,表中其他其他字段都依赖于主键,因此第二范式只要记住主键约束就好了
第三范式就是要求表中不能有其他表中存在的、存储相同信息的字段,通常实现是在通过外键去建立关联,因此第三范式只要记住外键约束就好了。

性能优化

delete 和 drop的区别:1. delete删除的是数据,drop删除的是表
2. delete每次删除一行数据,同时在redo和undo中记录操作,
可回滚
3. delete可以删除指定数据,如果不指定,则删除所有数据。
4. drop删除的是表结构和数据,并释放所占有的空间。{drop>delete} 执行速度,drop>delete

对一个读多写少的大表添加字段或索引:
1. 普通的添加字段sql:
ALTER TABLE table_name
ADD COLUMN num int(10) NOT NULL DEFAULT 0 AFTER addtime
2. 普通的添加索引sql
ALTER TABLE table_name ADD INDEX num (num) ;
3. 数据量很大的表
① 创建一个临时的新表,首先复制旧表的结构(包含索引)
② 给新表加上新增的字段
③ 把旧表的数据复制过来
④ 删除旧表,重命名新表的名字为旧表的名字
4. 3提到的方法在数据量大时耗时过长,且会影响业务运行,所以可以使用
在线ddl工具:pt-online-schema-change

Mysql的性能优化:1. 对查询进行优化,要尽量避免全表扫描,首先应考虑在 where 及
order by 涉及的列上建立索引。
2. 应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描
3. 应尽量避免在 where 子句中使用 != 或 <> 操作符,否则将引擎放弃使用索引而进行全表扫描。
4. 应尽量避免在 where 子句中使用 or 来连接条件,如果一个字段有索引,一个字段没有索引,将导致引擎放弃使用索引而进行全表扫描
5. in 和 not in 也要慎用,否则会导致全表扫描
6. like模糊全匹配也将导致全表扫描

实现数据库幂等需求

幂等:其任意多次执行所产生的影响均与一次执行的影响相同
1、建立数据库唯一索引
在数据库中创建唯一索引,用作幂等记录,可以防止插入重复数据。以一个插入业务数据的场景为例,可通过业务维度定义唯一索引作为幂等记录,在插入数据方法中,首先查询该幂等记录是否存在,如果存在则直接返回第一次执行的结果,如果不存在则继续执行,并发场景中可能存在多个线程同时插入幂等记录的情况,这种情况下唯一索引可确保只有一个线程可以插入幂等记录成功,其余线程抛异常。插入幂等记录成功的线程可以继续执行后续操作,抛异常的线程执行事务回滚操作
2、全局唯一ID
3、去重表
4、基于版本控制的乐观锁
基于版本控制的乐观锁有多种实现方式,比如基于数据库的版本控制乐观锁实现、基于redis的版本控制乐观锁实现等,以数据库的版本控制乐观锁为例:update table set version=version+1 where id=#{id} and version=#{version}

索引

目的:提高查询效率,就像有了字典查单词效率高
原理:通过不断的缩小想要获得数据的范围来筛选出最终想要的结果,同时把随机的事件变成顺序的事件

索引分类

(1)单列索引:一个索引只包含单个列,但一个表中可以有多个单列索引
• 普通索引:MySQL中基本索引类型,没有什么限制,允许在定义索引的列中插入重复值和空值,纯粹为了查询数据更快一点。
• 唯一索引:索引列中的值必须是唯一的,但是允许为空值
• 主键索引:是一种特殊的唯一索引,不允许有空值
(2)组合索引:
在表中的多个字段组合上创建的索引,只有在查询条件中使用了这些字段的左边字段时,索引才会被使用,使用组合索引时遵循最左前缀集合
(3)全文索引:全文索引,只有在MyISAM引擎上才能使用,只能在CHAR,VARCHAR,TEXT类型字段上使用全文索引
什么是全文索引:就是在一堆文字中,通过其中的某个关键字等,就能找到该字段所属的记录行,比如有"你是个大煞笔,二货 …" 通过大煞笔,可能就可以找到该条记录。这里说的是可能,因为全文索引的使用涉及了很多细节
(4)空间索引:空间索引是对空间数据类型的字段建立的索引
MySQL中的空间数据类型有四种,GEOMETRY、POINT、LINESTRING、POLYGON。
在创建空间索引时,使用SPATIAL关键字。
要求:引擎为MyISAM,创建空间索引的列,必须将其声明为NOT NULL

创建索引

CREATE UNIQUE INDEX indexName ON mytable(username(length))
ALTER table mytable ADD UNIQUE [indexName] (username(length))

索引组合查询

最左缀原则,在检索数据时从联合索引的最左边开始匹配,类似于给(a,b,c)这三个字段加上联合索引就等于同时加上了 (a) (ab) (abc) 这三种组合的查询优化

建立索引原则

1、最左前缀匹配原则,非常重要的原则,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的
2、=和in可以乱序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式
3、尽量选择区分度高的列作为索引
4、索引列不能参与计算,保持列“干净”,比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,原因很简单,b+树中存的都是数据表中的字段值,但进行检索时,需要把所有元素都应用函数才能比较,显然成本太大。
5、尽量的扩展索引,不要新建索引。

索引存储类型是B+树

磁盘IO是非常高昂的操作,计算机操作系统做了一些优化,当一次IO时,不光把当前磁盘地址的数据,而是把相邻的数据也都读取到内存缓冲区内,因为局部预读性原理告诉我们,当计算机访问一个地址的数据的时候,与其相邻的数据也会很快被访问到。
我们需要的数据结构能够做些什么:每次查找数据时把磁盘IO次数控制在一个很小的数量级(最好是常数数量级。

B/B+树是为了磁盘或其它存储设备而设计的一种平衡多路查找树(相对于二叉,B树每个内节点有多个分支),与红黑树相比,在相同的的节点的情况下,一颗B/B+树的高度远远小于红黑树的高度。对查找的方式进行优化,熟悉的二分查找,二叉树可以把速度提升到O(log(n,2)),查询的瓶颈在于树的深度,最坏的情况要查找到二叉树的最深层,由于,每查找深一层,就要访问更深一层的索引文件。在多达数G的索引文件中,这将是很大的开销。所以,尽量把数据结构设计的更为‘矮胖’一点就可以减少访问的层数。B+树的父节点也必须存在于子节点中,是其中最大或者最小元素,B+树的节点只存储索引key值,具体信息的地址存在于叶子节点的地址中。这就使以页为单位的索引中可以存放更多的节点。减少更多的I/O支出
b+树是按照从左到右的顺序来建立搜索树的,

事务ACID

所谓事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。

原子性是指事务是一个不能分割的工作单位,事务中的操作要么都发生,要么都不发生

一致性是指在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。这是说数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性。

隔离性是多个事务并发访问时,事务之间是隔离的,一个事务不应该影响其它事务运行效果
这指的是在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。
事务查看数据更新时,数据所处的状态要么是另一事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看到中间状态的数据。

持久性,即事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。

事务的(ACID)特性是由关系数据库管理系统实现的。
数据库管理系统采用日志来保证事务的原子性、一致性和持久性。日志记录了事务对数据库所做的更新,如果某个事务在执行过程中发生错误,就可以根据日志,撤销事务对数据库已做的更新,使数据库退回到执行事务前的初始状态。
数据库管理系统采用锁机制来实现事务的隔离性。当多个事务同时更新数据库中相同的数据时,只允许持有锁的事务能更新该数据,其他事务必须等待,直到前一个事务释放了锁,其他事务才有机会更新该数据。

事务的隔离级别

概念:多个事务之间隔离的,相互独立的。但是如果多个事务操作同一批数据,则会引发一些问题,设置不同的隔离级别就可以解决这些问题。
存在问题:
1.脏读:一个事务,读取到另一个事务中没有提交的数据
未commit也被另一个进程读取了
当一个事务rollback后,另一个进程数据也跟着改变了
2.不可重复读(虚读) : 在同一个事务中,两次读取到的数据不一样。
3.幻读:一个事务操作(DML )数据表中所有记录,另一个事务添加了一条数据,则第一 个事务查询不到自己的修改。*隔离级别:

四个隔离级别

  1. read uncommitted :读未提交
    *产生的问题:脏读、不可重复读、幻读
  2. read committed :读已提交
    *产生的问题:不可重复读、幻读
    仅当commit以后另一个进程才会修改数据,但是两次读数不一致,仍有不可重复读的问题
  3. repeatable read :可重复读(MySQL)
    *产生的问题:幻读
    仅当commit了另一个进程后再查询才会修改数据
    解决了不可重复读
  4. serializable :串行化:若一个事务在操作一张表,另一个事务不可以同时操作这张表
    *可以解决所有的问题
    左边事务操作时,右边事务无法进行查询
    仅当commit后,才可以进行查询
    *注意:隔离级别从小到大安全性越来越高,但是效率越来越低

*未提交读(Read Uncommitted)最低的隔离级别。允许脏读(dirty reads),但不允许更新丢失,事务可以看到其他事务“尚未提交”的修改。
*提交读(Read Committed)允许不可重复读取,但不允许脏读取。这可以通过“瞬间共享读锁”和“排他写锁”实现。
读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行。
*可重复读(Repeatable Read)禁止不可重复读取和脏读取,但是有时可能出现幻读数据。这可以通过“共享读锁”和“排他写锁”实现。
读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务。
*可序列化(Serializable)最高的隔离级别,它要求事务序列化执行,事务只能一个接着一个地执行,不能并发执行。仅仅通过“行级锁”是无法实现事务序列化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作的事务访问到。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值