关系型数据库基础总结

关系型数据库架构

整体思维架构

架构

  • 如何设计一个关系型数据库

    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....

理论范式

猜你喜欢

转载自www.cnblogs.com/xujie09/p/11595589.html