JAVA备忘录(三):数据库面试题

一.基本概念

1.超键,候选键,主键,外键是什么
超键:在关系中能够唯一标识一个元组的属性集称为超键。超键可以是一个属性,也可以是多个属性的组合。
候选键:不含多余元素的超键。也就是说,只要删除候选键中的任意一行属性,它就不再能唯一标识一个元组了。
主键:由用户自主选择的能唯一标识一个元组的键,它是超键的一部分。主键的取值不能为空。
外键:在一个关系模式中,存在一个属性,它是其他关系模式的主键,那么称其为当前关系模式的外键。

参考: SQL–超键、候选键、主键、外键的认识和区分.

2.为什么选择自增列作为主键。
	如果选择自增列作为主键,每次插入新纪录时,直接添加在当前记录末尾的后续位置即可,当一个页写满了,就会
开辟一个新的页。
	而如果使用非自增列作为主键,比如说像身份证号码,学号这样近似无规则的属性。那么数据块为了维护索引,
会频繁地进行移动原有的数据,分页等操作。一来会增加大量的开销,二来分页操作会导致大量的碎片,使得
索引结构不紧致。
	例如在聚集索引中,插入一个随机索引值的数据可能会使数据库为了维护索引而大量地对原有数据进行物理地址的
移动。而在非聚集索索引中,则涉及指针的变动。
3.触发器的作用
	触发器是一种特殊的存储过程,主要是通过事件来触发执行的,这些事件包括UPDATE,DELETE,和INSERT操作。
触发器的使用可以强化约束,保证数据库的完整性和一致性,使数据库中的数据符合我们想要的约束。

参考: 数据库之——触发器(学习笔记).

4.存储过程是什么?
	存储过程是一个预编译的SQL语句,优点是允许模块化的设计,就是说只需要创建一次,以后在程序中就可以调用
多次。由于它是预编译的,所以它的执行比单纯SQL语句执行要快。如果遇到需要频繁调用同一个SQL语句的时候,
可以使用存储过程。

参考: SQL存储过程使用介绍.

5.存储过程的优缺点。
优点:
1.若SQL语句比较复杂,存储过程可以封装此类语句,使我们的SQL语句变得精简。
2.存储过程在创建时就已经被编译并加载到是数据库中,所以存储过程的执行比单个SQL语句的执行要快。
3.在调用时只需要提供存储过程名以及必要的参数信息,一定程度上看见可以减轻网络负担。
4.增强安全性。通过授权可以使用户只能访问存储过程,而无法访问整个表。
缺点:
1.可移植性差。
6.什么叫视图?什么叫游标?
	视图通常是具有一个表或者多个表的行与列的一个子集,视图是一个虚拟的表,具有和物理表相同的功能,
对视图的增删改查也会影响物理表的数据。当SQL语句比较复杂时(比如涉及多表连接),可以使用视图来简化我们的
SQL语句。
	游标是查询结果集的一个指针。游标可以被定在查询结果集的特定行,然后向前或者向后进行检索,且每次只能检索
一行,并且游标可以对当前行进行修改。如果需要逐条处理数据的时候,游标显得很重要。

参考: 让数据库游标变得简单.

7.视图的优缺点?
优点:
1.简化SQL语句,用户可以通过简单的查询从复杂查询中获得结果。
2.提高安全性。视图可以有选择性地选择数据库中的一部分,从而避免把整个表暴露给用户。
缺点:
查询视图时,必须把视图的查询转化为对基本表的查询,如果这个视图由一个复杂的多表查询来定义,则无法进行
数据更改
8.drop,truncate,delete的区别?
	1)从删除内容上来说,
		drop删除的是整个表,包括表结构,表相关的触发器,索引等。而与此表有关联的存储过程
	和函数将会被保留,但其状态会变为invalid;
		truncate删除的是表中的数据,表结构和索引等内容会恢复到初始状态。再次插入时,自增id从1开始。
	且该删除不会触发相关的触发器
		delete是逐行删除,并且会触发相关的触发器。且不会减少表和索引所占用的空间。
	2)从事务上来说
		truncate和drop所执行的删除是不放到rollback segment中,也就是说这两个操作不能被回滚。且这两个
	操作不会将单独的删除操作记录在日志中,只会记录整个删除操作本身;而delete操作是可以被回滚的,
	且会被记录日志中。如果在事务相关的场景,要谨慎使用drop和truncate。
	3)从性能上来说
		truncate的执行要比delete删除全表数据的执行要快速。因为truncate所用到的系统和事务,日志等资源
	更少。
9.什么是临时表,临时表什么时候删除?
临时表可以手动删除:  DROP TEMPORARY TABLE IF EXISTS temp_table;
临时表只在当前连接中可见,当关闭连接时,数据库会自动删除所有临时表并释放所有空间。因此在不同连接中可以创建
同名临时表。
创建临时表的语法与创建表语法类似,不同之处是增加关键字TEMPORARY,
如:
CREATE TEMPORARY TABLE tmp_table (

NAME VARCHAR (10) NOT NULL,

time date NOT NULL
);

select * from tmp_table;
10.非关系型数据库和关系型数据库的区别,优势比较?
非关系型数据库的优势:
性能:NoSQL是基于key-value存储的,不需要经过SQL层的解析,数据间没有复杂的逻辑关系,所以性能非常高。
可扩展性:数据间没有耦合性,所以非常容易进行水平扩展。
关系型数据库的优势:
复杂查询:可以在多个表之间进行复杂的数据查询,表中的数据关系更贴合现实。
事务支持:使得对于安全性能要求很高的数据访问要求得以实现。
11.数据库的三大范式。
第一范式:数据库表中的所有字段都是不可分解的原子值,就说明该数据库表满足第一范式。遵循第一范式可以使用
表中数据分类变得更加容易,提高了数据库的性能。
第二范式:在第一范式的基础上,要求数据库表中的每一列都与主键相关,而不允许存在多种数据保存在同一张数据库
表中。也就是说,一个数据表中只能描述一件事情。
第三范式:在第二范式的基础上,要求数据库表中的每一列都只能与主键相关,而不能与其他列相关,用外键完成表
之间的关联这样使得一个逻辑关系数据库中表达的隔离性高,耦合度低,有利于提高数据库性能,防止数据冗余。

参考: 数据库设计三大范式.

13.什么是内连接,外连接,交叉连接,笛卡儿积?
	内链接:只连接匹配的行  如 INNER JOIN
	左外连接:包含左边表的全部行(无论是否匹配)以及右边表中的匹配行。 如LEFT JOIN
	右外连接:包含左边表的匹配行,以及右边表的全部行(无论是否匹配) 如 RIGHT JOIN
	全外连接:包含左右表的全部行,无论他们是否互相匹配。 如 FULL JOIN
	交叉连接: 生成笛卡尔积-它不使用任何匹配或者选取条件,而是直接将一个数据源中的每个行
与另一个数据源的每个行都一一匹配
14.char和varchar的使用场景?
	1.char的长度是不可变的,而varchar的长度是变化的。  如果存进去的字符串长度小于声明时的长度,
对char来说,它会在字符串末尾补上空格,使得其长度与声明时长度相等。对varchar来说,它会调整自身
长度变得与字符串长度一样。
	2.char的存取速度比varchar要快,这是因为char的长度固定,便于查找。而varchar是属于牺牲时间换空间。
	3.char的存储方式是:英文字符占一个字节,汉字占两个字节。 而varchar的存储方式是:英文和汉字都占用
两个字节。
15.like % 和_的区别?
%百分号通配符可以表示任意字符出现任意次数(包括0次)。
_下划线通配符只能匹配单个字符,不能多也不能少。
like是模糊查询。会降低性能:比如InnoDB对于模糊查询会弃行级锁而使用表级锁。
16.最左前缀原则?
多列索引:ALTER TABLE people ADD INDEX lname_fname_age (lame,fname,age);

为了提高搜索效率,我们需要考虑运用多列索引,由于索引文件以B-Tree格式保存,
所以我们不用扫描任何记录,即可得到最终结果。

注:在mysql中执行查询时,只能使用一个索引,如果我们在lname,fname,age上分别
建索引,执行查询时,只能使用一个索引,mysql会选择一个最严格(获得结果集记录数最少)的索引。

最左前缀原则:顾名思义,就是最左优先,上例中我们创建了lname_fname_age多列索引,
相当于创建了(lname)单列索引,(lname,fname)组合索引以及(lname,fname,age)组合索引。

二.锁

1.InnoDB用的是什么锁模式,分别是哪几种?
Innodb引擎所使用的是行级锁模式。主要有共享锁,排它锁,意向共享锁,意向排它锁,间隙锁。
共享锁(S):允许一个读取数据事务去读一行,同时阻止其他事务获得相同数据集的排它锁。
排它锁(X):允许获得排它锁的事务更新数据,同时阻止其他事务获得相同数据集的共享锁和排它写锁。
意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。
意向排他锁(IX):事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁。
间隙锁:当使用范围条件而不是相等条件进行检索数据的时候,InnoDB会给所有符合条件的索引项加锁(无论这个索引
项是否存在),而这些不存在,又被加上锁的索引项就成为“间隙”。这样做的目的是防止幻读(在下一次检索时发现插入
了一条原先没有,但是符合条件的数据),以满足高隔离性的需要。但是给不存在的索引项加上锁很可能会导致INSERT
操作被堵塞,会造成严重的锁等待。所以在实际开发中,尤其是插入比较多的业务之中,尽量使用相等条件而不是范围
条件去进行检索

参考: 了解下Mysql的间隙锁及产生的原因.

2.InnoDB行锁的实现方式?
InnoDB行锁的实现方式在MySQL与Oracle中有所区别。
在MySQL中,InnoDB行锁是通过给索引上的索引项加锁来实现的。所以只有通过索引项来检索数据,MySQL才会加上行级锁,
否则将会使用表锁,会引起并发性能降低或者锁冲突
在Oracle中,InnoDB行锁是通过在数据块中的数据行加锁来实现的。
3.什么时候应该在InnoDB中使用表锁
主要有两种情景
1.事务需要对表中的大量数据进行更新,如果使用行锁的话可能会使执行速度降低,其他事务需要进行长时间的锁等待
或者锁冲突,此时应该使用表锁来提升事务的执行速度
2.事务涉及多个表的连接,如果使用行锁很可能会造成死锁,造成大量事务回滚,此时应该使用表锁。
4.MyISAM表锁的实现
MyISAM中的表级锁又两种模式:表共享锁和表独占写锁。
对MyISAM的读操作,不会堵塞其他用户对同一个表的读请求,但会堵塞用户对同一个表的写请求。
对MyISAM的写操作,会堵塞其他用户对同一个表的读操作和写操作

参考: MySQL中的锁(表锁、行锁).

5.什么是死锁
当两个事务都需要对方持有的排它锁才能完成事务,导致了循环锁等待,就是死锁。
6.MySQL有哪些锁?
从锁定粒度来看,MySQL有三种锁的级别:页级,表级,行级。
	表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
	行级锁:开销大,加锁慢;会出现死锁,锁定粒度小,发生锁冲突的概率最高,并发度最高。
	页级锁:开销,加锁时间,锁粒度,并发度介于表级锁和行级锁之间。会出现死锁。
7.数据库中的乐观锁和悲观锁?
	乐观锁:在并发场景下,乐观地认为事务之间的操作互不影响,无需得到锁便开始执行事务,在事务提交之前再进行
检查该行数据在事务执行期间是否被修改过,若是,则该事务回滚,若否,则提交该事务。
		  一般的实现方式为给数据表加上数据版本字段(version)。在对数据进行修改操作之前,把数据连同其
		版本号一起查询出来,然后把版本号+1,执行事务。在提交事务之前,对比事务中的版本号是否比数据表中的
		版本号大,如果是,说明这期间没有其他事务操作该数据,事务进行提交。否则,事务回滚。
		
	悲观锁:悲观地认为发生事务冲突的概率很大,所以在执行事务之前,要获得对应数据的锁,共享锁和排它锁都是
	    属于悲观锁。悲观锁是数据库原生支持的,也就是通过select.....for update触发。当数据库执行该
	    SQL语句时,会给对应的数据行加上行级锁,因此其他执行该命令并试图选中同一行数据的操作就会被排斥,
	    等待行锁的释放。、
		   另外需要注意的是,在MySQL中,select for update语句执行所扫描过的行都会被加上行级锁,这一点
	    很容易造成问题。因此在MySQL中如果要使用悲观锁,务必要根据索引项进行检索,而不是全表扫描
	    (变成了表级锁)
8.什么场景使用乐观锁,什么场景使用悲观锁?
要从三个角度去考虑:
	冲突频率:如果是一个冲突频率很高的场景,建议采用悲观锁保证成功率。因为乐观锁在不发生取锁失败的情况下
开销比悲观锁小,但一旦发生失败而造成事务回滚的话,开销则比较大。所以在冲突频率高的场景下要使用悲观锁保证
成功率。
	响应速度:如果对响应速度的要求很高,则建议采用乐观锁,成功就执行,不成功就失败,无需像悲观锁一样需要
等待其他并发释放锁才能执行事务。、
	重试代价:如果重试代价大,建议使用悲观锁。

三.引擎(InnoDB与MyISAM)

1.聚集索引和非聚集索引的区别是?
聚集索引和非聚集索引的共同点是所用的都是B+树索引。主要区别在于:
1.聚集索引叶节点储存的是数据块,而非聚集索引的叶子节点储存的是数据块的指针。
2.聚集索引能直接查找数据块,而在非聚集索引上,如果查询列包含了没有被索引覆盖的列,则需要进行二次查询
(在辅助索引B+树上找到该列对应的主键,然后去主索引B+树上检索到数据块)。
所以如果查询业务比较多的场景,适合使用聚集索引。而如果需要频繁修改数据值,适合使用非聚集索引,因为聚集
索引需要移动数据的物理位置
3.查询,更新操作较多的场景适合用聚集索引,插入操作较多的场景适合用非聚集索引(无需改变物理地址,只需改变
指针即可)

参考: 原理剖析:InnoDB与MyISAM 聚集索引与非聚集索引.

2.InnoDB与MyISAM有哪些主要区别?
1.MyISAM是非聚集索引,InnoDB是聚集索引。故MyISAM更适合插入的场景,InnoDB更适合查询与更新的场景。?
2.InnoDB支持事务操作,外键。而MyISAM不支持
3.InnoDB使用行级锁,MyISAM使用表级锁。但InnoDB使用行级锁并不是确定的。当查询列中出现了没有被索引项
覆盖的属性时,InnoDB不知道应该锁住哪一行元组,此时就会使用表级锁对全表加锁。
4.删表的时候。InnoDB不会重新建立表,而是一行行删除。
5.对于AUTO_INCREMENT字段。InnoDB中,该字段必须是索引,若是组合索引,该字段必须是组合索引中的第一列,
但在MyISAM中,同样的,它也必须是索引,但若是组合索引,它可以不是组合索引中的第一列
6.行数查询时,InnoDB不保存行数,而是扫描全表。而MyISAM只需读取保存的行数即可。
7.MyISAM中允许没有任何索引和主键的表存在,但InnoDB中不允许没有设定索引和主键,若用户没有显式声明,就会
自动生成一个6字节的主键(用户不可见)

四.索引

1.什么是索引?
	数据库会维护一个用于组织数据和排序数据的数据结构,在这个数据结构上可以实现高级查找算法。这种数据结构
就是索引。
	数据库中索引的实现通常使用B+树或者B树
2.索引的作用?优缺点?
作用:协助快速查询,更新数据库表中的数据。
优点:
	1.可以大大加快数据检索的速度,这是创立索引的最主要原因。
	2.通过创建唯一性索引,可以保证数据表中每一行数据的唯一性。
	3.	加快表与表之间的连接,特别是在实现数据完整性上特别又意义。
	4.	在使用分组和排序子句进行数据检索时,可以显著减少查询中分组和排序的时间。
缺点:
	1.创建索引和维护索引需要额外的时间和系统开销,且随着数据量的增加,情况越严重。
	2.索引需要占物理空间。特别是在聚集索引中,数据块直接连同索引一起被加载到内存中,占用内存比较大。
	3.对表中数据进行添加,删除,修改的时候,索引也需要动态维护,比如说插入一条数据可能会使原有的一部分数据
	物理地址发生移动
3.哪些列适合建立索引,哪些不适合?
适合建立索引的列:
	1.在经常需要搜索的列上建立索引,可以加快搜索速度。
	2.在作为主键的列上,可以强制该列的唯一性并且组织表中数据的排序结构。
	3.在经常需要进行连接的列上(主要是外键),可以提高链表速度。
	4.在经常需要进行范围搜索或者排序的列上,因为索引已经排序过了,所以会加快查询时间。
	5.在经常出现在WHERE子句中的列,加快条件的判断速度。
不适合建立索引:
	1.查询中很少用到的列。根据非索引项进行检索并不会提高检索速度,反而索引的创建与维护要增加系统开销。
	2.对text,image等数据类型不宜建立索引,单个索引的内容太多,会大大增加维护索引的开销。
	3.当对修改性能的需求大于查询性能的需求时,不应该使用索引。因为索引的建立实际上就是牺牲了修改性能
	用来提高查询性能。
4.MySQL中B+树索引与Hash索引的区别?
Hash索引储存的实际上是键值的Hash值,因此检索的时候可以一次定位(o(1)时间复杂度)
而B+树索引检索数据需要从根节点到叶节点,最后才能访问到数据,这期间需要进行多次IO访问,时间复杂度为o(logn)
5.为什么不都用Hash索引而使用B+树索引
	1.因为Hash索引检索数据的方式实际上是通过键值的Hash值来进行一次定位,而Hash值是经过Hash算法处理
之后的结果,并不能保证和Hash运算之前相等,所以Hash索引只能进行对等查询,比如说”=“和”IN“,而不能进行
范围查询和模糊查询。
	2.Hash索引无法避免数据的排序操作。因为索引的排序顺序是Hash值的排序顺序,而Hash值是经过Hash计算
处理之后的结果,并不能保证和Hash计算之前相等,所以无法避免数据的排序操作。
	3.Hash索引不能通过部分索引进行查询。在组合索引中,Hash索引其实是把索引中所有属性合并之后一起计算
Hash值,所以如果使用组合索引中的一部分索引键进行查询的话,Hash索引不起作用。
	4.Hash索引无法避免表扫描。由于不同的键值有可能得到相同的Hash值,所以即使获得了某条满足Hash值的数据
时,也无法直接从索引中直接完成查询,而是还要到数据表中进行比对。
	5.Hash索引如果遇到大量Hash值相等的情况,性能并不一定比B+树高。此时一个Hash值对应了多条数据,再进行
目标数据的定位就要进行表扫描,这样会增加系统开销。
6.B树和B+树的区别?
	B树之中,每一个节点都存储着数据,并且叶子节点指针为NULL,叶子节点不包含任何关键字信息。
	而在B+树中,所有的数据都存储在叶子节点,且叶子节点也按照关键字的大小从小到大进行连接,所有的非叶子节点
都是索引部分。
7.为什么说B+比B树更适合实际应用中操作系统的文件索引和数据库索引?
	1.B+的磁盘读写代价更低
	B+的内部结点并没有指向关键字具体信息的指针。因此其内部结点相对B树更小。
如果把所有同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多。一次性读入内存
中的需要查找的关键字也就越多。相对来说IO读写次数也就降低了。
	2.B+树的查询效率更加稳定。
	B+树的非叶子节点并没有储存数据,而是存了数据的索引,所有数据都储存在叶子节点之中,所有数据的查询都
需要从根节点遍历到叶节点,所有数据查询经过的路径长度相同,导致每一个数据查询效率相当。
8.为什么使用B+树作索引而不是普通的二叉树?
	使用B+树而不使用二叉树的主要原因是磁盘寻址加载次数上。
	磁盘储存数据的单位是页,当一页写满了,就会到另一页上进行储存。而树结构的节点在物理内存是不连续的,
所以不同节点之间的跳转可能会涉及磁盘的分页查找,这会影响性能。
	而B+树的特点就是“矮胖”,在相同数据量下,B+树的高度比二叉树要小,所以查找一个数据,所要遍历的节点数也
更少,故磁盘寻址加载次数要更少,效率更高。
发布了7 篇原创文章 · 获赞 2 · 访问量 456

猜你喜欢

转载自blog.csdn.net/SCUTJAY/article/details/104054837
今日推荐