数据库常见面试题
1.sql的执行顺序fromwheregroup byhavingselectdistinctorder bylimit2.mysql的存储引擎存储引擎有MyISAM和InnoDBmysql的默认引擎是InnoDB两者的区别InnoDB是事务性的存储引擎、MyISAM是非事务的MyISAM表锁InnoDB有表锁、行锁行锁sql条件中命中索引的就是行锁(死锁、锁冲突几率低、并发高)表锁行锁失效就自动升级为表锁(不易死锁、锁冲突几率高、并发低)表锁有2种模式共享读锁一个线程获得锁之后其他线程对同一表能进行读操作独占写锁会阻塞其他线程对同一表的写操作3.#{}与${}的区别#是预编译的、$是字符串替换#可以防止sql注入#会被替换成、$会被替换成变量的值PS:有一些特殊情况比如 like 时如果使用#{}需要拼接例如CONCAT(%, #{ruleName,jdbcTypeVARCHAR},%)4.为什么使用B树作为mysql的索引数据结构mysql数据存储在硬盘中不能一次性把数据加载到内存中1B树只有叶子节点存储数据基于这种特性数据的查询不需要跨层遍历。比如select * from user where id10;只需要找到id10的节点遍历链表就可以找到往后的记录2树的高度低检索速度越快这里提一下B树和B树的区别3B树叶子节点有双向链表便于遍历数据B树是Node节点存储数据B树是叶子节点存储数据5.数据库优化加索引如果数据量特别大的话索引也是无效的可以在查数据库之前加一层缓存表结构的优化选择合适的数据类型和范式优化sql语句的优化①不用*而是列出所有列②减少表的连接③用in代替or④避免在where子句中写!或、null判断⑤避免前边有表达式或函数⑥避免使用模糊查询xxx%提到索引那么想来说说最左匹配原则知道这个有利于我们对sql进行优化。6.最左匹配原则假设联合索引a,b,c范围条件in、between…and…、、、!①当条件中某个参数是范围查询那么该参数后的索引就不走了比如where a1 and b3 and c4此时索引只走a、b②当条件中索引顺序变了此时要分2种情况1abc都是非范围查询此时依旧走索引mysql查询优化器会自动优化where条件顺序2当遇到范围查询整个条件中的所有字段不走索引③当遇到函数、表达式时此字段及以后的都就不走索引比如where FORMAT(a,yyyy-MM-dd)2021-07-23 and b1 and c0此时都不走索引。但是有时候可以优化为表达式或者函数在后边比如a/39 可以优化为a27where b1 and c0 and FORMAT(a,yyyy-MM-dd)2021-07-23把a放在后边在都是非范围的条件下bc走索引。④条件中只有bc 此时不走索引7.mysql事物原子性要么都执行成功、要么都执行失败undo log日志记录修改前信息持久性事物一旦提交、改变是永久的(redo log记录某个页上进行了什么修改)隔离性并发事物之间是相互隔离的隔离级别读未提交、读已提交、可重复读、串行化一致性事务的执行保证数据库从一个一致的状态转变为另一个一致的状态一致性是事物的目的原子性、隔离性、持久性是实现一致性的手段脏读一个事物读取了另外一个事物的没提交的数据幻读针对 insert、delete 相同条件下2次读取的结果条数不一致不可重复读针对update一个事物对于同一数据2次读取结果不一致事务的隔离级别读未提交 、读已提交、可重复读、序列化在读未提交的情况下读不加锁写加锁就会引发脏读mysql InnoDB采用MVCC多版本并发控制解决了这个问题MVCC是通过生成数据快照只在读已提交和可重复生效。read commit是语句级快照repeatable read是事务级的快照读已提交解决了脏读是在读取的时候生产“版本号”等其他事务commit后读取最新的版本号数据否则读取旧版本数据可重复读隔离级别存在“幻读”问题mysql的默认隔离级别是可重复读在InnoDB引擎快照读MVCC解决了幻读问题因为它是读历史版本的数据MVCCMVCC多版本并发控制比如session1对数据进行修改在事务提交前后session2读取的结果不一致而MVCC解决了读写操作的阻塞问题在更新记录时原始记录保存到undo空间表多个数据版本形成链表mysql根据回滚指针和事务id来判断数据版本的可见性当前行 → undo版本2 → undo版本1 → NULL每个版本都带着事务这样就可以通过mvcc去根据版本链和事务id去过滤Mvcc多版本并发控制他具体实现就是在读的时候会创建读视图可以理解为就是一个对象这个对象里存了活跃事务id也就是未提交的事务id然后其他事务读的时候就能根据活跃事务id去版本链过滤掉未提交的那些版本就看不到了读已提交解决了脏读问题在这个隔离级别下事务当中的每次读都会生成一个读视图然后过滤掉未提交的事务版本保证读到的都是已提交的这就解决了脏读可重复读解决了脏读不可重复读和快照读的幻读问题我们正常写的sql都是快照读加for update 的叫当前读当前读的幻读是由间隙锁解决的可重复读级别下事务第一次读的时候生成读视图后续读都复用这个读视图幻读不可重复读 也是根据事务id过滤过滤了未提交的事务版本以及当前事务开启后其他事务提交的版本详解可借鉴https://cloud.tencent.com/developer/article/24491478.回表介绍回表前要先了解聚簇索引和非聚簇索引聚簇索引存储主键和当前行数据非聚簇索引存储主键和索引举个例子user表的主键id索引是name其他列是age。此时非聚簇索引文件中存储的id,name如果我们要查询age,条件是name那么需要先根据name查询出主键id,再到聚簇索引文件中找age这个过程叫做回表回表是指使用查询数据时非聚簇索引想要的结果可能包含其他列比如orderName但是只能查出来主键和索引id和orderId这个时候会根据主键再去查询其他列orderName避免回表建立联合索引使得想要的列在索引中……9.主从库主从库实现读写分离主库接收写请求从库接收读请求从库数据由主库发送binlog进行更新。10.分库分表单个数据库分成多个数据库数据分散的分部到多个数据库单个表分成多个表数据分散到多个表11.SQL执行计划explain关键字 用于查看慢sql的原因EXPLAINSELECT id from hr_staff_info where member_nameXXX;其中有几个关键字段select_type查询类型普通查询SIMPLE、联合查询、子查询(subquery)type(连接类型):all(全表扫描)range(范围扫描)ref(使用了不为主键和unique的索引)eq_ref(使用了主键或者唯一键查询)const (表中一条匹配记录一次查到)possible_keys(可能用到的索引)key(实际用到的索引)rows(扫描的行数)扫描的行数越少越好比如表有10w数据扫描了10w就是全表扫描了多表连接查询执行计划怎么看多表连接每一行对应每张表的访问计划第一行是驱动表会先被扫描用他的结果匹配后边的表。后边的表是被驱动表被循环匹配。比如AB两表连接A的主键和B的非唯一索引是连接条件那么B表的执行计划type就是ref12.索引包括哪些索引包括普通索引、唯一索引、主键索引、联合索引导致索引失效的几种情况遇到null值模糊查询 xxx%使用or最左匹配原则where 11前边有表达式或函数使用类型隐式转化比如a是varchar类型sql中写a1这样13.mybatis分页是如何实现的通过page对象作为分页依据通过count作为查询总条数限制对原有sql通过limit进行分页14.like %和like _的区别%代表任意多个字符_代表任意一个字符。15.什么是存储过程有哪些优缺点存储过程相当于编程语言中的函数封装了我们的代码存储过程的优点封装代码保存在数据库中让编程语言调用存储过程是预编译代码块执行效率高存储过程代替大量的sql语句降低网络通信量提高通信效率存储过程的缺点每个数据库的存储过程语法不一样不通用业务逻辑放在数据库上难易迭代16.数据库范式你了解哪些第一范式属性的原子性列不可再分。第一范式是所有关系型数据库的基础不满足第一范式的数据库就不是关系型数据库第二范式每个属性都必须完全依赖全部主键不允许部分依赖第三范式每个非主属性都不传递依赖于R的候选码不允许传递依赖BC范式每个属性都不传递依赖于R的候选码17.什么是视图视图的使用场景有哪些视图是一种虚拟的表可以对数据库进行增、改、查操作。视图中可以包括一个表或多个表的行与列对视图的操作不影响基本表它使得我们获取数据更容易。应用场景不希望访问者获取整个表的信息只是暴露部分字段给访问者所以创建一个虚表查询数据来源于不同表查询者希望以统一的方式查询建立视图可以多表查询效率也高18. drop、delete、truncate的区别drop是删除表内容及结构、不可回滚、不可带where、删除速度快delete是删除表中指定行数据、可回滚、可带where、删除速度慢truncate是删除表中的内容表结构还保留、不可回滚、不带where、删除速度快19.触发器的作用触发器是与表相关的数据库对象在满足定义条件时触发并执行触发器中定义的语句集合。触发器的这种特性可以协助应用在数据库端确保数据库的完整性20.varchar和char的区别varchar和char都是数据库中用于描述字符串的类型char是定长的varchar是不定长的。比如定义一个char[10]和一个varchar[10],如果存进去的都是‘test’,那么char还是占用10个长度而varchar就会占用4个长度。所有char适合用于存放定长的字段varchar适合用于存放不定长的字段。char的存取速度比varchar要快