Java关系型数据库相关⾯试题
1、⼿撕sql
有学⽣表、课程表、成绩表,计算平均成绩⼤于等于60的学⽣id、学⽣姓名和平均成绩。
select s.s_id,s.s_name,avg(sc.score)
from score sc
left join student s on sc.s_id=s.s_id
group by s.s_id having avg(sc.score>=60)
可能引发问题
(1)⼏种join的区别
1).以A,B两张表为例
A left join B
选出A的所有记录,B表中没有的以null 代替
2).right join 同理
3).inner join
A,B的所有记录都选出,没有的记录以null代替
4).cross join (笛卡尔积)
A中的每⼀条记录和B中的每⼀条记录⽣成⼀条记录
例如A中有4条,B中有4条,cross join 就有16条记录
(2)常见复杂sql的语法格式
select column, group_function(column)
from table
[where condition]
ajax定时轮询[group by group_by_expression]
[order by column];
where -> group by -> having -> order by -> limit (顺序不能错)
2、Mysql中的索引类型
index ---- 普通索引,数据可以重复,没有任何限制。
unique ---- 唯⼀索引,要求索引列的值必须唯⼀,但允许有空值;如果是组合索引,那么列值的组合必须唯⼀。
primary key ---- 主键索引,是⼀种特殊的唯⼀索引,⼀个表只能有⼀个主键,不允许有空值,⼀般是在创建表的同时创建主键索引。
组合索引 ---- 在多个字段上创建的索引,只有在查询条件中使⽤了创建索引时的第⼀个字段,索引才会被使⽤。
fulltext ---- 全⽂索引,是对于⼤表的⽂本域:char,varchar,text列才能创建全⽂索引,主要⽤于查
⽂本中的关键字,并不是直接与索引中的值进⾏⽐较。fulltext更像是⼀个搜索引擎,配合match against操作使⽤,⽽不是⼀般的where语句加like。
注:全⽂索引⽬前只有MyISAM存储引擎⽀持全⽂索引,InnoDB引擎5.6以下版本还不⽀持全⽂索引
所有存储引擎对每个表⾄少⽀持16个索引,总索引长度⾄少为256字节,索引有两种存储类型,包括B+树索引和哈希索引。
索引可以提⾼查询的速度,但是创建和维护索引需要耗费时间,同时也会影响插⼊的速度,如果需要插⼊⼤量的数据时,最好是先删除索引,插⼊数据后再建⽴索引。
3、索引失效条件
不在索引列上做任何操作(计算、函数、(⾃动or⼿动)类型转换),会导致索引失效⽽转向全表扫描
存储引擎不能使⽤索引范围条件右边的列
尽量使⽤覆盖索引(只访问索引的查询(索引列和查询列⼀致)),减少select *
mysql在使⽤不等于(!=或者<>)的时候⽆法使⽤索引会导致全表扫描
is null,is not null也⽆法使⽤索引
like以通配符开头(’%abc…’)mysql索引失效会变成全表扫描的操作。社保个人网页
mysql面试题acid假设
index(a,b,c)
最左前缀匹配:模糊查询时,使⽤%匹配时:’a%‘会使⽤索引,’%a‘不会使⽤索引
条件中有or,索引不会⽣效
a and c,a⽣效,c不⽣效
b and c,都不⽣效
a and
b > 5 and c, a和b⽣效,c不⽣效。
4、覆盖索引
5、B+树索引和hash索引的⽐较
Hash 索引仅仅能满⾜"=",“IN"和”<=>"查询,不能使⽤范围查询。
游戏的源代码是什么由于 Hash 索引⽐较的是进⾏ Hash 运算之后的 Hash 值,所以它只能⽤于等值的过滤,不能⽤于基于范围的过滤,因为经过相应的Hash 算法处理之后的 Hash 值的⼤⼩关系,并不能保证和Hash运算前完全⼀样。
Hash 索引⽆法被⽤来避免数据的排序操作。
由于 Hash 索引中存放的是经过 Hash 计算之后的 Hash 值,⽽且Hash值的⼤⼩关系并不⼀定和 Hash 运算前的键值完全⼀样,所以数据库⽆法利⽤索引的数据来避免任何排序运算;
Hash索引不能利⽤部分索引键查询。
对于组合索引,Hash 索引在计算 Hash 值的时候是组合索引键合并后再⼀起计算 Hash 值,⽽不是单独计算 Hash 值,所以通过组合索引的前⾯⼀个或⼏个索引键进⾏查询的时候,Hash 索引也⽆法被利⽤。
Hash 索引在任何时候都不能避免表扫描。
前⾯已经知道,Hash 索引是将索引键通过 Hash 运算之后,将 Hash运算结果的 Hash 值和所对应的⾏指针信息存放于⼀个 Hash 表中,由于不同索引键存在相同 Hash 值,所以即使取满⾜某个 Hash 键值的数据的记录条数,也⽆法从 Hash 索引中直接完成查询,还是要通过访问表中的实际数据进⾏相应的⽐较,并得到相应的结果。
Hash索引遇到⼤量Hash值相等的情况后性能并不⼀定就会⽐B-Tree索引⾼。
对于选择性⽐较低的索引键,如果创建 Hash 索引,那么将会存在⼤量记录指针信息存于同⼀个 Hash 值相关联。这样要定位某⼀条记录时就会⾮常⿇烦,会浪费多次表数据的访问,⽽造成整体性能低下。
6、索引的底层实现(B+树,为何不采⽤红⿊树,B树)
索引使⽤B+树的原因:
索引查过程中就要产⽣磁盘I/O消耗,主要看IO次数,和磁盘存取原理有关。
根据B-Tree的定义,可知检索⼀次最多需要访问h个节点。数据库系统的设计者巧妙利⽤了磁盘预读原理,将⼀个节点的⼤⼩设为等于⼀个页,这样每个节点只需要⼀次I/O就可以完全载⼊
局部性原理与磁盘预读
7、Mysql存储引擎 MyISAM 和 InnoDB
MyISAM存储引擎的特点是:表级锁、不⽀持事务和⽀持全⽂索引
InnoDB存储引擎的特点是:⾏级锁、事务安全(ACID兼容)、⽀持外键、不⽀持FULLTEXT类型的索引(5.6.4以后版本开始⽀持FULLTEXT类型的索引)。InnoDB存储引擎提供了具有提交、回滚和崩溃恢复能⼒的事务安全存储引擎。InnoDB是为处理巨⼤量时拥有最⼤性能⽽设计的。它的CPU效率可能是任何其他基于磁盘的关系数据库引擎所不能匹敌的。
注意:
InnoDB表的⾏锁也不是绝对的,假如在执⾏⼀个SQL语句时MySQL不能确定要扫描的范围,InnoDB表同样会锁全表(锁完以后,判断不符合条件的会逐步解锁),
例如update table set num=1 where name like “a%”。
适⽤场景
MyISAM适合:
1). 做很多count 的计算;
2). 插⼊不频繁,查询⾮常频繁,如果执⾏⼤量的SELECT,MyISAM是更好的选择;
3). 没有事务。
InnoDB适合:
1). 可靠性要求⽐较⾼,或者要求事务;
2). 表更新和查询都相当的频繁,并且表锁定的机会⽐较⼤的情况指定数据引擎的创建;
3). 如果你的数据执⾏⼤量的INSERT或UPDATE,出于性能⽅⾯的考虑,应该使⽤InnoDB表;可画canvas网页版
4).DELETE FROM table时,InnoDB不会重新建⽴表,⽽是⼀⾏⼀⾏的 删除;
5).LOAD TABLE FROM MASTER操作对InnoDB是不起作⽤的,解决⽅法是⾸先把InnoDB表改成MyISAM表,导⼊数据后再改成InnoDB表,但是对于使⽤的额外的InnoDB特性(例如外键)的表不适⽤。
8、数据库三范式
1)、第⼀范式:
当关系模式R的所有属性都不能在分解为更基本的数据单位时,称R是满⾜第⼀范式的,简记为1NF。满⾜第⼀范式是关系模式规范化的最低要求,否则,将有很多基本操作在这样的关系模式中实现不了。(属性的原⼦性约束,不可在分解)
2)、第⼆范式:
如果关系模式R满⾜第⼀范式,并且R得所有⾮主属性都完全依赖于R的每⼀个候选关键属性,称R满⾜第⼆范式,简记为2NF。(⾮主键属性完全依赖于主键属性)
3)、第三范式:
设R是⼀个满⾜第⼀范式条件的关系模式,X是R的任意属性集,如果X⾮传递依赖于R的任意⼀个候选关键字,称R满⾜第三范式,简记为3NF。(⾮主键属性不能出现依赖传递)
9、事务ACID
原⼦性(Atomic):不可分割的操作单元,事务中所有操作,要么全部成功;要么撤回到执⾏事务之前的状态
计算机二级c语言证书⼀致性(Consistency):如果在执⾏事务之前数据库是⼀致的,那么在执⾏事务之后数据库也还是⼀致的;
隔离性(Isolation):事务操作之间彼此独⽴和透明互不影响。事务独⽴运⾏。这通常使⽤锁来实现。⼀个事务处理后的结果,影响了其他事务,那么其他事务会撤回。事务的100%隔离,需要牺牲速度。
持久性(Durability):事务⼀旦提交,其结果就是永久的。即便发⽣系统故障,也能恢复。
10、事务隔离级别
未提交读(Read Uncommitted):允许脏读,其他事务只要修改了数据,即使未提交,本事务也能看到修改后的数据值。也就是可能读取到其他会话中未提交事务修改的数据
提交读(Read Committed):只能读取到已经提交的数据。Oracle等多数数据库默认都是该级别 (不重复读)。
可重复读(Repeated Read):可重复读。⽆论其他事务是否修改并提交了数据,在这个事务中看到的数据值始终不受其他事务影响。存在幻读问题
串⾏读(Serializable):完全串⾏化的读,每次读都需要获得表级共享锁,读写相互都会阻塞。
MySQL数据库(InnoDB引擎)默认使⽤可重复读( Repeatable read)
事务并发问题:
1)、脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据
2)、不可重复读:事务 A 多次读取同⼀数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同⼀数据时,结果 不⼀致。
3)、幻读:系统管理员A将数据库中所有学⽣的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插⼊了⼀条具体分数的记录,当系统管理员A改结束后发现还有⼀条记录没有改过来,就好像发⽣了幻觉⼀样,这就叫幻读。
⼩结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满⾜条件的⾏,解决幻读需要锁表
11、⼤表优化
限定数据的范围: 务必禁⽌不带任何限制数据范围条件的查询语句。⽐如:我们当⽤户在查询订单历史的时候,我们可以控制在⼀个⽉的范围内。
读/写分离: 经典的数据库拆分⽅案,主库负责写,从库负责读;
缓存:使⽤MySQL的缓存,另外对重量级、更新少的数据可以考虑使⽤应⽤级别的缓存;
垂直分区:
根据数据库⾥⾯数据表的相关性进⾏拆分。 例如,⽤户表中既有⽤户的登录信息⼜有⽤户的基本信息,可以将⽤户表拆分成两个单独的表,甚⾄放到单独的库做分库。
简单来说垂直拆分是指数据表列的拆分,把⼀张列⽐较多的表拆分为多张表。 如下图所⽰,这样来说⼤家应该就更容易理解了。
垂直拆分的优点: 可以使得⾏数据变⼩,在查询时减少读取的Block数,减少I/O次数。此外,垂直分区可以简化表的结构,易于维护。
垂直拆分的缺点: 主键会出现冗余,需要管理冗余列,并会引起Join操作,可以通过在应⽤层进⾏Join来解决。此外,垂直分区会让事务变得更加复杂;
⽔平分区
保持数据表结构不变,通过某种策略存储数据分⽚。这样每⼀⽚数据分散到不同的表或者库中,达到了分布式的⽬的。 ⽔平拆分可以⽀撑⾮常⼤的数据量。
⽔平拆分是指数据表⾏的拆分,表的⾏数超过200万⾏时,就会变慢,这时可以把⼀张的表的数据拆成多张表来存放。举个例⼦:我们可以将⽤户信息表拆分成多个⽤户信息表,这样就可以避免单⼀表数据量过⼤对性能造成影响。
⽔平拆分可以⽀持⾮常⼤的数据量。需要注意的⼀点是:分表仅仅是解决了单⼀表数据过⼤的问题,但由于表的数据还是在同⼀台机器上,其实对于提升MySQL 并发能⼒没有什么意义,所以⽔平拆分最好分库 。
⽔平拆分能够 ⽀持⾮常⼤的数据量存储,应⽤端改造也少,但 分⽚事务难以解决 ,跨界点Join 性能较差,逻辑复杂。
12、分库分表带来的问题
事务⼀致性问题
跨节点关联查询 join 问题
跨节点分页、排序、函数问题
全局主键避重问题
数据迁移、扩容问题
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论