关系型数据库架构
整体思维架构
架构
-
如何设计一个关系型数据库
1、需要一个文件存储系统(RDBMS) 2、需要一个程序实例(对存储系统进行逻辑管理) 包括:存储管理、缓存机制、SQL解析、日志管理、权限划分、容灾机制、索引管理、锁管理
索 引
- 为什么要使用索引
快速查询数据
- 什么样的信息能成为索引
主键、唯一键以及普通键等
-
索引的数据结构
1、生成索引,建立二叉查找树进行二分查找 2、生成索引,建立B-Tree结构进行查找 3、生成索引,建立B+-Tree结构进行查找 4、生成索引,建立Hash结构进行查找
B-Tree定义:
1、根节点至少包括两个孩子
2、树种每个节点最多含有m个孩子(m>=2)
3、除根节点和叶节点外,其他每个节点至少有ceil(m/2)(取上限)个孩子
4、所有叶子节点都位于同一层
5、
B+-树的定义
1、非叶子节点的子树指针与关键字个数相同
2、非叶子节点的子树P[i],指向关键字值[K[i],K[i+1]]的子树
3、非叶子节点仅用来索引,数据都保存在子节点中
4、所有叶子节点均 有一个链指针指向下一个叶子节点
hash索引的缺点:
1、仅仅能满足 “=”,“in”,不能使用范围查询
2、无法被用来避免数据的排序操作
3、不能利用部分索引键查询
4、不能避免表扫描
5、遇到大量Hash值相等的情况后性能并不一定就会比B-Tree索引高
BitMap索引:
很少数据库支持BIgMap索引
结论: 1、B+树的磁盘读写代价更低 2、B+树的查询效率更加稳定 3、B+树更有利于对数据库的扫描
-
密集索引和稀疏索引的区别
1、密集索引文件中的每个搜索码值都对应一个索引值
2、稀疏索引文件只为索引码的某些值建立索引项
InnoDB:
1、若一个主键被定义,该主键则作为密集索引;
2、若没有主键被定义,该表的第一个唯一非空索引则作为密集索引
3、若不满足以上条件,innodb内部会生成一个隐藏主键(密集索引)
4、非主键索引存储相关键位和其对应的主键值,包含两次查找
-
如何定位并优化慢查询Sql
-
根据慢日志定位慢查询sql
show variable like '%quer%' #查询数据库相关变量 'slow_query_log' ——查看是否打开了慢日志查询功能; ‘slow_query_log_file’ ——慢查询日志的存放位置; ‘long_query_time’ ——多长时间的查询被定义为慢查询,单位为 秒;
show status like '%slow_queries%'; #查看有多少慢sql
-
使用explain等工具分析sql
explain + sql ;
explain关键字段:
1、type:
system>const>eq_ref>ref>fulltext>ref_or_null>index_merge>unique_sunquery>index_subquery>range>index>all 最后两个是 index和all 表示是全表扫描,sql需要优化;
2、extra:
当该字段出现以下2项以为着mysql根本不能使用索引,效率会受到重大影响,应尽可能对此进行优化。
- Using filesort:表示mysql会对结果使用一个外部索引排序,而不是从表里按索引次序读到相关内容。可能在内存或者磁盘上进行排序。mysql中无法利用索引完成的排序操作称为“文件排序
- Using temporary:表示mysql在对查询结果排序时使用临时表。常见于排序order by 和分组查询 group by。
-
修改sql或者尽量让sql走索引
-
-
联合索引的最左匹配原则成因
1、最左匹配原则,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如a=3 and b=4 and c>5 and d=6 如果建立(a、b、c、d)顺序的索引,d是用不到索引的,如果建立(a、b、d、c)的索引则都可以用到,a、b、d的顺序可以任意调整。
2、=和in 可以乱序,比如a=1 and b=2 and c=3建立(a,b,c)索引可以任意顺序,mysql的查询优化器会自动优化。
成因:
mysql 会对联合索引从左到右 先后执行 order by col1(第一个字段)、col2(第二个字段),所以直接上来使用第二个字段无法使用索引
-
索引是建立得越多越好吗
1、数据量小的表不需要建立索引,建立会增加额外的索引开销 2、数据变更需要维护索引,因此更多的索引以为着更多的维护成本 3、更多的索引意味着也需要更多的空间
锁
数据库锁的分类
1、按锁的粒度分类:表级锁、行级锁、页级锁
2、按锁级别划分:共享锁、排它锁
3、按锁的方式划分:自动锁、显式锁
4、按操作划分,可分为DML锁,DDL锁
5、按使用方式划分,可分为乐观锁、悲观锁
MyISAM与InnoDB关于锁方面的区别是什么
-
MyISAM默认用的是表级锁,不支持行级锁;
适合场景: 1、频繁执行全表count语句 2、对数据进行增删改的频率不高,查询非常频繁 3、没有事务
-
InnoDB默认用的是行级锁,也支持表级锁;
1、数据增删改查都相当频繁 2、可靠性要求比较高,要求支持事务
共享锁(对数据库表的读操作)
在并发情况下,如果对一张表(记录)加了共享锁的情况下,其他session可以继续加共享锁;
在并发情况下,如果对一张表(记录)加了排他锁,无论共享锁和排他锁都无法再加;
排它锁(对数据库表的写操作)
在并发情况下,如果对一张表(记录)加了共享锁的情况下,无论共享锁和排他锁都无法再加;
在并发情况下,如果对一张表(记录)加了排他锁的情况下,无论共享锁和排他锁都无法再加;
InnoDB查询语句在走索引的时候,是行级锁以及gap锁
InnoDB查询语句在不走索引的时候,是表级锁
关闭mysql InnoDB的自动提交事务功能;
set autocommit = 0 #关闭自动提交;
手动加共享锁:select xxxx lock in share mode;
数据库事务的四大特性
-
原子性
-
一致性
-
隔离性
-
持久性
事务隔离级别以及各级别下的并发访问问题
1、更新丢失(我和别人同时开启事务,自己在更新表数据进行提交时,覆盖了别人比我先提交的更新)——mysql所有事务隔离级别在数据库层面上均可避免
2、脏读(读到了别人没有提交的数据)——read-committed事务隔离级别以上可避免
3、不可重复读(第一次读和第二次读由于别人提交了一个事务,导致我前后读取同一个数据不一致)——repaeatabe-read事务隔离级别以上可避免
4、幻读(第一次读和第二次读由于别人提交了一个事务,导致我前后读取的数据条数不一致)——serializable事务隔离级别可避免
oracle默认事务级别是:read-commit
mysql默认事务级别是:repeatable-read
查看数据库的隔离级别:
select @@tx_isolation;
设置隔离级别等级:
set session transaction isolation level read uncommitted;
注意:与 SQL 标准不同的地方在于InnoDB 存储引擎在 REPEATABLE-READ(可重读)事务隔离级别下使用的是Next-Key Lock 锁算法,因此可以避免幻读的产生,这与其他数据库系统(如 SQL Server)是不同的。所以说InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重读) 已经可以完全保证事务的隔离性要求,即达到了 SQL标准的SERIALIZABLE(可串行化)隔离级别。
InnoDB可重复读隔离级别下如何避免幻读
表象:快照读(非阻塞)——伪MVCC
当前读(加了锁的增删改查):
select .... lock in share mode; select ...for update; update,delete,insert
快照读(不加锁的非阻塞读):
select ...
内在:next-key锁(行锁+gap锁)
- 对主键索引或者唯一索引会用Gap锁吗
- 如果where条件全部命中,则不会用Gap锁,只会加记录锁;
- 如果where条件部分命中或者全不命中,则会加Gap锁;
- Gap锁会用在非唯一索引或者不走索引的当前读中;
笔记:gap就是间隙锁,就是在对表某几行进行操作的时候,为了防止出现幻读(我在未提交事务的时候,别人对表进行了删除和插操作),会在命中条件的几个行的间隙行区间里加上锁,别人无法进行删除插入操作。
RC、RR级别下的InnoDB的非阻塞读(快照读)如何实现
1、数据行里DB_TRX_ID(事务标识符),DB_ROLL_PTR ,DB_ROW_ID字段 ;
2、undo日志
3、 read view
语法
group by分组
- 满足select子句中的列名必须为分组列或者函数
- 列函数对于group by 子句定义的每个组各返回一个结果
having
统计相关:count,sum,max,min....