# 技术栈知识点巩固——数据库

Posted MarlonBrando1998

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了# 技术栈知识点巩固——数据库相关的知识,希望对你有一定的参考价值。


mysql 基本语法

Oracle简单语法 Mybatis结合使用

MySQL 的基础架构


Sql执行过程


数据库索引常识

聚簇索引与非聚簇索引的区别
  • 聚簇索引:将数据存储与索引放到一起,找到索引就找到了数据。
  • 非聚簇索引:数据存储与索引分开存放

非聚簇索引一定会回表查询吗
  • 不一定,查询语句所要求的字段如果全部命中了索引,那么就不必再进行回表查询。

Mysql 索引是怎么放的

Mysql 索引使用注意事项
  • 索引对NULL的值无效。
  • 使用短索引
  • 索引列排序的时候如果where条件中已经使用了索引,那么OrderBy是无法使用索引的
  • like %test% 不会使用索引而like test%可以使用索引
  • 不要在列上进行运算,索引会失效
  • 避免在 where 子句中使用 !=not in<> 操作符
  • 复合索引遵守“最左前缀”原则

索引有哪些优缺点?索引有哪几种类型?创建索引优有什么原则呢?

最左前缀匹配原则
  • 在MySQL建立联合索引时会遵守最左前缀匹配原则,即最左优先,在检索数据时从联合索引的最左边开始匹配。
  • 例如含有组合索引(a,b,c)索引命中的条件:aababc

如何写sql能够有效的使用到复合索引
  • 例如含有复合索引(a,b,c)
  • 索引命中的条件:aababc

覆盖索引、回表
  • 回表:先通过普通索引的值定位聚簇索引值,再通过聚簇索引的值定位行记录数据,需要扫描两次索引B+树,它的性能较扫一遍索引树更低。
  • 覆盖索引:只需要在一棵索引树上就能获取SQL所需的所有列数据,无需回表,速度更快。

Hash索引和B+树


数据库索引为什么要用 B+树不用二叉树?
  • 二叉树每个节点只有两个子节点,如果是一颗单边二叉树,查询某个节点的次数与节点所处的高度相同,时间复杂度为O(n);如果是一颗平衡二叉树,查找效率高出一半,时间复杂度为O(Log2n)
  • B+树:应文件系统所需而产生的一种B树的变形树。B+树的磁盘读写代价更低,查询效率更稳定,对范围查询的支持更好。

说说分库与分表的设计(不使用中间件)
垂直分
  • 按照业务模块进行分库分表操作,各模块有各自的库表。
  • 优缺点:更具业务层次解耦,高并发下一定程度的提升IO数据库连接等。数据聚合查询比较麻烦,分布式事务处理复杂,存在单表数据量过大。
水平分
  • 根据表内数据内在的逻辑关系,将同一个表按不同的条件分散到多个数据库或多个表中,每个表中只包含一部分数据。
  • 优缺点:不存在单表数据量过大,提升系统的稳定性。数据聚合查询不方便,数据扩展难度和维护量大。

优化SQL
  • 使用explain查看自己编写的Sql执行情况。
  • 写的Sql尽量满足最左索引匹配原则使用索引。
  • 知道查询结果限制结果。
  • 知道查询的列就不要select *

MySQL 的Explain


  • select_type:对应行是简单还是复杂的查询。
  • possible_keys:查询可能使用哪些索引来查找。
  • key:mysql实际采用哪个索引来优化对该表的访问。
  • key_len:mysql在索引里使用的字节数。
  • Extradistinct: 一旦mysql找到了与行相联合匹配的行,就不再搜索了,Using index:这发生在对表的请求列都是同一索引的部分的时候,返回的列数据只使用了索引中的信息,而没有再去访问表中的行记录。是性能高的表现。

InoDB与MyISAM的区别
InnoDBMyISAM
支持事务不支持事务
支持外键不支持外键
表数据文件本身就是按B+Tree组织的一个索引结构,必须要有主键,通过主键索引效率很高索引和数据文件是分离的,索引保存的是数据文件的指针
Innodb不支持全文索引支持全文索引
InnoDB支持表、行(默认)级锁MyISAM支持表级锁
InnoDB表必须有唯一索引(没有指定的话会自己找生产一个隐藏列Row_id来充当默认主键)Myisam可以没有

InnoDB引擎的4大特性

limit 100000 加载很慢的话,你是怎么解决的呢
  • order by命中索引,在limit
分布式主键方案
  • 数据库自增长序列或字段
  • UUID
  • Redis 生成 ID

事务的隔离级别有哪些?MySQL的默认隔离级别是什么?
  • Mysql:默认为可重复读
  • Oracle:默认为都已提交
隔离级别说明
DEFAULT使用数据库的默认级别,Mysql(可重复读),Oracle(读已提交)
READ_UNCOMMITTED读未提交(脏读)最低的隔离级别
READ_COMMITTED读已提交,ORACLE默认隔离级别,有幻读以及不可重复读风险
REPEATABLE_READ可重复读,解决不可重复读的隔离级别,但还是有幻读风险
SERIALIZABLE最高的事务隔离级别,不管多少事务,挨个运行完一个事务的所有子事务之后才可以执行另外一个事务里面的所有子事务,这样就解决了脏读、不可重复读和幻读的问题了

什么是幻读,脏读,不可重复读呢?
  • 幻读:在一个事务内,同一个Select语句在不同时间执行。得到不同的结果集。
  • 脏读:读到的数据已经被修改了,不是最新的记录。
  • 不可重复读:事务B 在 事务A 提交前读到的结果,和在 事务A 提交后读到的结果可能不同。不可重复读出现的原因就是由于事务并发修改记录而导致的。

在高并发情况下,如何做到安全的修改同一行数据
  • Synchorized
  • lock
  • redis

数据库的乐观锁和悲观锁
悲观锁
  • 悲观锁,正如其名,具有强烈的独占和排他特性。它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。
乐观锁
  • 乐观锁( Optimistic Locking ) 相对悲观锁而言,乐观锁机制采取了更加宽松的加锁机制。悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性。但随之而来的就是数据库性能的大量开销,特别是对长事务而言,这样的开销往往无法承受。而乐观锁机制在一定程度上解决了这个问题。乐观锁,大多是基于数据版本( Version )记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个 “version” 字段来实现。读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号等于数据库表当前版本号,则予以更新,否则认为是过期数据。

Mysql 日志存形式
  • 重做日志redo:在页修改的时候,先写到 redo log buffer 里面, 然后写到 redo log 的文件系统缓存里面,然后再同步到磁盘文件。

  • 回滚日志Undo: 当事务对数据库进行修改,InnoDB引擎不仅会记录redo log,还会生成对应的undo log日志;如果事务执行失败或调用了rollback,导致事务需要回滚,就可以利用undo log中的信息将数据回滚到修改之前的样子。


Innodb的事务与日志的实现方式
  • 利用回滚日志(undo log) 和 重做日志(redo log)两种方式实现事务。
  • 因为事务在修改页时,要先记 undo,在记 undo 之前要记 undoredo
  • 然后修改数据页,再记数据页修改的 redo
  • Redo(里面包括 undo 的修改) 一定要比数据页先持久化到磁盘。
  • 当事务需要回滚时,因为有undo,可以把数据页回滚到前镜像的状态,崩溃恢复时,如果 redo log 中事务没有对应的 commit 记录,那么需要用 undo把该事务的修改回滚到事务开始之前。
  • 如果有 commit 记录,就用redo前滚到该事务完成时并提交掉。
MySQL事务的四大特性以及实现原理
  • 原子性:要么全成功、要么全失败。
  • 一致性:同一个事物,读取到的内容应该是一致的,不变的。
  • 隔离性:不同事物之间相互独立互不干扰。
  • 持久性:事务提交后,事务内操作的数据因该持久化到数据库中。

如果某个表有近千万数据,CRUD比较慢,如何优化
  • 修改查询Sql尽可能的满足索引列去查询。
  • 做水平分表操作。
  • 避免查询全部分页查询。

mysql中in 和exists的区别
  • 如果子查询得出的结果集记录较少,主查询中的表较大且又有索引时应该用in, 反之如果外层的主查询记录较少,子查询中的表大,又有索引时使用exists
  • in 是把外表和内表作hash连接,而exists是对外表作loop循环,每次loop循环再对内表进行查询
explain
select * from tb_data where data_code like 'code11%'
and id in (select id from tb_data where data_code like 'code11%')
		
		
explain
select x.* from tb_data x where x.data_code like 'code11%'
and exists (select id from tb_data where data_code like 'code11%')



数据库自增主键可能遇到什么问题
  • 分表的时候主键会重复。
  • oracledb2采用SequencemysqlsqlServer又采用自增长,通用性不好。

Mysql中有哪几种锁


为什么要使用视图?什么是视图?
  • 视图是虚拟的,物理上是不存在的。视图本身并不包含任何数据,它只包含映射到基表的一个查询语句,当基表数据发生变化,视图数据也随之变化。

  • 使用视图,可以定制用户数据,得到特定的数据。

  • 使用试图,可以简化数据查询操作。

  • 比较安全,用户对视图中的数据,不能随意的修改。


视图有哪些特点?哪些使用场景?
  • 视图是虚拟表,数据不能修改。
  • 视图不能索引,不能有相关联的触发器和默认值。
  • 可以选择我们需要的列重新组成一张表,或者是可以存放一些统计数据。

视图的优点、缺点
  • 简单、安全、逻辑数据独立性。
  • 数据量大了之后,影响视图中数据的维护。

什么是游标?
  • 游标(Cursor)是处理数据的一种方法,为了查看或者处理结果集中的数据,游标提供了在结果集中一次一行或者多行前进或向后浏览数据的能力。

什么是存储过程?有哪些优缺点?
  • 存储过程是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,它存储在数据库中,一次编译后永久有效,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。
  • 优点:存储过程是一个预编译的代码块,执行效率比较高;存储过程在服务器端运行,减少客户端的压力;允许模块化程序设计,只需要创建一次过程,以后在程序中就可以调用该过程任意次,类似方法的复用;一个存储过程替代大量T_SQL语句 ,可以降低网络通信量,提高通信速率;可以一定程度上确保数据安全。

什么是触发器?触发器的使用场景有哪些?
  • 提供给程序员和数据分析员来保证数据完整性的一种方法,它是与表事件相关的特殊的存储过程,它的执行不是由程序调用,也不是手工启动,而是由事件来触发。
  • 记录对某张表的操作可以使用触发器,例如记录历史数据。

MySQL中都有哪些触发器?
  • Before Insert
  • After Insert
  • Before Update
  • After Update
  • Before Delete
  • After Delete

count(1)、count(*) 与 count(列名)
  • count(列名):不会算为null的值。
  • count(*)count(1)差不多。

drop、delete与truncate的区别
  • delete:每次删除一行,都在事务日志中为所删除的每行记录一项。删除表中数据而不删除表的结构(定义),同时也不释放空间。
  • drop:立即执行,执行速度最快、删除内容和定义,释放空间。
  • truncate:是DDL语言, 操作立即生效,自动提交,原数据不能回滚,操作不触发trigger

UNION与UNION ALL的区别
  • union查询会去重,因为要去重所以效率低
  • unionall查询不会去重

字段为什么要求定义为not null
  • 如果不设置NOT NULL的话,NULL是列的默认值,如果不是本身需要的话,尽量就不要使用NULL
  • 如果使用索引,就要避免列设置成NULL
  • 索引列,会带来的存储空间的问题,需要额外的特殊处理,还会导致更多的存储空间占用

Blob和Text区别
  • TEXTBLOB的主要差别就是BLOB保存二进制数据,TEXT保存字符数据。目前几乎所有博客内容里的图片都不是以二进制存储在数据库的,而是把图片上传到服务器然后正文里使用标签引用,这样的博客就可以使用TEXT类型。而BLOB就可以把图片换算成二进制保存到数据库中。

varchar(50)、int(20)、char(20)
  • 可变长度,存储ANSI字符,根据数据长度自动变化。

  • varchar(50):最多存放50个字符。

  • char是存储字符(无论字母还是汉字都最多存255个),char(20)表示这个字段最多存20个字符

    如果存了16个字符 那么也会占用20个字符的空间。

  • int(20)的作用于int的范围明显是无关的,int(20)只是用来显示数据的宽度。


数据库的三大范式
一范式
  • 表中的列不可分割,确保列的原子性。例如地址字段:青海省海东市乐都区,这个列可以分为(省、市、区)
二范式
  • 在一范式的基础上,表中的每个列属性完全依赖于主键,一张表中只能保存一种数据。例如:订单表中,存订单编号、商品编号就可以了。
三范式
  • 在二范式的基础上,确保每列都和主键列直接相关,而不是间接相关。比如在设计一个订单数据表的时候,可以将客户编号作为一个外键和订单表建立相应的关系。而不可以在订单表中添加关于客户其它信息(比如姓名、所属公司等)的字段。

SQL 约束
  • 主键约束
  • 外键约束:两表之间建立关系并引用主表的列。
  • 检查约束:数据的检查,例如范围。
  • 默认约束:默认值。
  • 唯一约束:唯一索引。

超键、候选键、主键、外键
  • 超键:在关系模式中,同时还要是唯一标识元组,而且还是属性集。
  • 候选键: 不含有多余属性的超键称为候选键。也就是在候选键中,若再删除属性,就不是键了。
  • 主键: 用户选作元组标识的一个候选键程序主键。
  • 外键:如果关系模式R中属性K是其它模式的主键,那么k在模式R中称为外键。
举例说明

学生表(学号,姓名,性别)成绩表(学号,课程,分数)

  • 在学生表中(学号、姓名)(学号、性别)为超键,属性集合含有唯一标识。
  • 学生表中(学号)是候选键
  • 主键:唯一表示,在这里可以是学号
  • 外键:成绩表中(学号)是外键。

Mysql 的内连接、左连接、右连接
  • 左连接:以左表中的数据为基础,右表中不存在的值都为NULL
  • 右连接:以右表中的数据为基础。
  • 内连接:两个表的交集,不存在一张表中数据为NULL

主键使用自增ID还是UUID
  • Oracle不支持自增主键、可以使用序列操作。
  • InnoDB存储引擎中,主键索引是作为聚簇索引存在的,如果主键索引是自增ID,那么只需要不断向后排列即可,如果是UUID,由于到来的ID与原来的大小不确定,会造成非常多的数据插入,数据移动,然后导致产生很多的内存碎片,进而造成插入性能的下降。

数据库连接池
  • 数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个。
  • 释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。这项技术能明显提高对数据库操作的性能。
  • 连接池的使用可看:https://blog.csdn.net/qq_37248504/article/details/115740440

Mysql有关权限的表
  • user权限表:记录允许连接到服务器的用户帐号信息,里面的权限是全局级的。
  • db权限表:记录各个帐号在各个数据库上的操作权限。
  • table_priv权限表:记录数据表级的操作权限。
  • columns_priv权限表:记录数据列级的操作权限。
  • host权限表:配合db权限表对给定主机上数据库级操作权限作更细致的控制。
Mysql字典表

Mysql自增主键用完了怎么办
  • int无符号的范围:0~4294967295,约43亿。
  • int修改为bigint

如何监控数据库?慢日志都是怎么查询的?
  • 使用druidSql监控。
  • show variables like '%query%';命令查看慢查询定义信息。

优化查询过程中的数据访问
  • 分页查询,针对大数据量。

  • 使用limit查询自己想要的数据。

  • 指定列名、避免使用SELECT *

  • 对经常查询的接口做缓存处理。

  • 使用explain进行分析。

  • 索引覆盖扫描,尽可能将列放到索引中,这样存储引擎不需要回表获取对应行就可以返回结果。

  • 改变数据库和表的结构,修改数据表范式。

  • 重写SQL语句,让优化器可以以更优的方式执行查询。


MySQL 死锁问题
  • 当两个及以上的事务,双方都在等待对方释放已经持有的锁或因为加锁顺序不一致造成循环等待锁资源,就会出现“死锁”

select for update
  • SELECT * from tb_data WHERE id ='00000d04336f4da9a6379184f4188434' for UPDATE;
    update tb_data set string1 = string1 - 1 where id = '00000d04336f4da9a6379184f4188434';
    
  • 排他锁的申请前提:没有线程对该结果集中的任何行数据使用排他锁或共享锁,否则申请会阻塞。


按照锁的粒度分,数据库锁有哪些呢?
  • 行级锁(INNODB引擎)、表级锁(MYISAM引擎)和页级锁(BDB引擎 )。

从锁的类别角度讲,MySQL都有哪些锁呢?
  • 共享锁: 又叫做读锁。 当用户要进行数据的读取时,对数据加上共享锁。共享锁可以同时加上多个。
  • 排他锁: 又叫做写锁。 当用户要进行数据的写入时,对数据加上排他锁。排他锁只可以加一个,他和其他的排他锁,共享锁都相斥。

行锁
  • 行级锁分为共享锁和排他锁。

  • mysql的行锁是基于索引加载的,所以行锁是要加在索引响应的行上

  • 自动加锁。对于UPDATEDELETEINSERT语句,InnoDB会自动给涉及数据集加排他锁;对于普通SELECT语句,InnoDB不会加任何锁;

  • 缺点:开销大;加锁慢;会出现死锁。

  • 优点:锁的粒度小,发生锁冲突的概率低;处理并发的能力强


表锁
  • 表锁响应的是非索引字段,即全表扫描,全表扫描时锁定整张表。
  • 自动加锁。查询操作(SELECT),会自动给涉及的所有表加读锁,更新操作(UPDATEDELETEINSERT),会自动给涉及的表加写锁。
  • 优点:开销小;加锁快;无死锁。
  • 缺点:锁粒度大,发生锁冲突的概率高,并发处理能力低。

页级锁
  • MySQL中锁定粒度介于行级锁和表级锁中间的一种锁。

  • 开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。


MySQL中InnoDB引擎的行锁是怎么实现的?
  • Record Lock:单个行记录上的锁,锁住索引记录,如果表没有设置任何索引,会使用隐式的主键来进行锁定。
  • Gap Lock:间隙锁,锁定一个范围,但不包含记录本身。
  • Next-Key LockGap LockRecord Lock组合,锁定一个范围,并且锁定记录本身。行的查询采用这种锁定算法。

如何删除大量数据
  • 先删除索引。
  • drop表,重新创建。

MySQL binlog的几种日志录入格式以及区别
  • Statement:每一条会修改数据的sql都会记录在binlog中。
  • RowRow不记录sql语句上下文相关信息,仅保存哪条记录被修改。
  • Mixed:混合使用rowstatement格式,对于DDL记录statument,对于table里的行操作记录为row格式。

以上是关于# 技术栈知识点巩固——数据库的主要内容,如果未能解决你的问题,请参考以下文章

# 技术栈知识点巩固——数据库

# 技术栈知识点巩固——算法

# 技术栈知识点巩固——Java集合

# 技术栈知识点巩固——Redis

# 全栈开发学习文档

# 技术栈知识点巩固——Js