找工作再也不愁之面试题全覆盖-数据库篇

数据库基础

求平局值用什么,分组用什么

统计平局值:avg

分组:group by

两个结果集求并集用什么

union 并集 , union all(允许重复)

完整查询SQL中的关键字的定义顺序

SELECT 列名 FROM 表1 JOIN 表2 ON 条件 WHERE 条件 GROUP BY 列名 HAVING 条件 ORDER BY 列名 LIMIT

完整的多表JOIN查询,SQL中关键字的执行顺序

FROM --> ON --> JOIN --> WHERE --> GROUP BY --> HAVING --> ORDER BY --> LIMIT

索引部分

什么是索引

索引是用来高效获取数据的存储结构如同字典的目录一样,数据库的索引通常使用b+tree来实现,索引树的节点和数据地址相关联,查询的时候在索引树种进行高效搜索,然后根据数据地址获取数据。索引提高了搜索的效率同时增加了索引维护的成本,滥用索引也会降低insert,update,delete的性能。

Mysql索引有哪些类型

普通索引:允许重复的值

唯一索引:不允许有重复的值

主键索引:数据库自动为我们的主键创建索引,如果我们没有指定主键,它会根据没有null的唯一索引创建主键索引,否则会默认根据一个隐藏的rowId作为主键索引

全文索引,用来对文本域进行索引,比如text,varchar,只针对MyISAM有效

索引方式有哪些

B+树和hash,Myisam和innodb都不支持hash

Mysql的索引结构原理

采用了B+树的数据结构,采用B+树的原因,B+树是多叉树,适合存储大量数据,B+树的数据存储在叶子节点,内部节点只存键值,因此B+树每次查询都要走到叶子节点, 查询性能更稳定,同时它的非叶子节点只存储key,因此每个节点能存储更多的key,树的高度变的更低,查询性能更快,而且它的叶子节点能够形成一个链表,支持范围查询,排序 。

InnoDB的索引结构和MyIsam的索引结构有什么区别

他们都是用的B+树,不同的是

  • innodb的叶子节点存放的是数据,myisam的叶子节点存放的是数据的地址
  • innodb中辅助索引的叶子节点存放的是主键索引的键值,myisam中辅助索引的叶子节点存放的也是数据的地址
  • innodb的索引和数据都存放到一个文件中,myisam的索引和数据分别存放到不同的文件中
哪些列不适合创建索引

不经常查询的列不适合创建索引

不出现在where中的字段不适合创建索引

离散度太低的字段不适合创建索引,比如性别

更新非常频繁的字段不适合创建索引,因为会导致索引频繁更细,性能差。

哪些因素会造成索引失效

模糊查询时,通配符放到左边的时候,会导致索引失效 比如 like ‘’%keyword%’’

列是字符串类型,查询条件没有用引号,会导致索引失效

使用了or,in,not in,not exist, !=等,会导致索引失效

查询null值,会导致索引失效

还有mySQL认为全表扫描会比索引查找快,就不会使用索引,比如表里只有一条记录

什么是辅助索引&什么是覆盖索引

除了主键索引之外的其他索引都叫辅助索引,也叫二级检索。辅助索引的叶子节点存储的是主键索引的键值,因此辅助索引扫描完之后还会扫描主键索引,这也叫回表

但是如果查询的列恰好包含在辅助索引的键值中,就不会再回表了,这也叫覆盖索引

InnoDB辅助索引的叶子节点也存数据吗

InnoDB辅助索引的叶子节点存放的是,主键索引的键值

因此辅助索引扫描完还会扫描主键索引,也叫回表

但是如果查询的列恰好包含在辅助索引的键值中,就不会再回表了,这也叫覆盖索引

组合索引的匹配原则

组合索引向左匹配,我们应该优先选择组合索引,因为对覆盖索引命中率更高,查询性能更高,但是应该考虑列的顺序,因为组合索引会向左匹配

Like一定会让索引失效吗

不一定,比如:like “值%” 一样可以使用索引,向左匹配,而 like "%值"或 "_值"就不能命中索引。

索引创建的原则有哪些

查询较频繁的列应该考虑创建索引

不经常查询的列不适合创建索引

不出现在where中的字段不适合创建索引

离散度太低的字段不适合创建索引,比如性别

更新非常频繁的字段不适合创建索引

数据库优化

哪些因素可能会造成数据库性能问题

不合理的商业需求,比如实时更新总注册人数,总交易额等等,应该考虑不要实时

对于热点数据的查询并发太高,应该考虑用缓存

数据库结构设计不合理,比如几十个字段集中在一张表,应该考虑分表

SQL语句有问题,比如太多JOIN,很多不需要的字段也要全部查询出来,应该考虑优化SQL

硬件和网络方面的影响

Mysql的执行流程是怎么样的

客户端发起SQL查询,首先通过连接器,它会检查用户的身份,包括校验账户密码,权限

然后会查询缓存,如果缓存命中直接返回,如果没有命中再执行后续操作,但是MySQL8.0之后已经删除了缓存功能

接下来到达分析器,主要检查语法词法,比如SQL有没有写错,总共有多少关键字,要查询哪些东西

然后到达优化器,他会以自己的方式优化我们的SQL

最后到达执行器,调用存储引擎执行SQL并返回结果

优化SQL你从哪些方面着手

不需要的字段就不要查询出来

小结果集驱动大结果集,将能过率更多数据的条件写到前面

in和not in尽量不要用,会导致索引失效

避免在where中使用or链接条件,这会导致索引失效

给经常要查询的字段建立索引

考虑如果不需要事务,并且主要查询的化,可以考虑使用MyISAM存储引擎

如果表数据量实在太庞大了,考虑分表

如何去定位慢SQL

通过druid连接池的内置监控来定位慢SQL

通过MySQL的慢查询日志查看慢SQL

通过show processlist,查看当前数据库SQL执行情况来定位慢SQL

页面上发起的一个查询很慢,你怎么去优化

首先看一下硬件和网络层面,有没有什么异常

然后分析代码有没有什么问题,算法有没有什么缺陷,比如多层嵌套循环

最后我们再定位到慢SQL,比如

  • 通过druid连接池的内置监控来定位慢SQL
  • 通过MySQL的慢查询日志查看慢SQL
  • 通过show processlist,查看当前数据库SQL执行情况来定位慢SQL

定位到慢SQL再考虑优化该SQL,比如说

  • 不需要的字段就不要查询出来
  • 小结果集驱动大结果集,将能过率更多数据的条件写到前面
  • in和not in尽量不要用,会导致索引失效
  • 避免在where中使用or链接条件,这会导致索引失效
  • 考虑如果不需要事务,并且主要查询的化,可以考虑使用MyISAM存储引擎

如果优化SQL后还是很慢,可以考虑给查询字段建索引来提升效率

如果建立索引了还是慢,看一下是不是数据量太庞大了,应该考虑分表了

你如何看SQL有没有命中索引

在SQL语句前加上explain,结果中的key就是实际用到的索引

mysql存储引擎有哪些,有什么区别,如何选择

主要有innodb,memory,myisam

innodb支持事务,速度相对较慢,支持外键,不支持全文索引

myisam 速度相对较快,支持全文索引,不支持外键,不支持事务,

memory不支持事务,基于内存读写,速度快,支持全文索引

如果对事务要求不高,而且是查询为主,考虑用myisam

如果对事务要求高,保存的都是重要的数据,建议使用innodb,它也是默认的存储引擎

如果数据频繁变化的,不需要持久化,可以使用memory

下面SQL如何优化

一个sql : select sum(amount) from recharge ,来查询总充值,recharge 表数据量达到了上千万,怎么优化

可以考虑建个汇总表来统计总充值,总订单数,总人数等等等

或者采用日报表,月报表,年报表,使用定时任务进行结算的方式来统计

或者看数据能不能使用ES搜索引擎来优化,如果非得要在这个上千万的表中来查询,那就采用分表

事务相关

什么是事务

一组对数据库的操作,把这一组看成一个再给你,要么全部成功,要么全部失败。

举个栗子,比如A向B转账,A账户的钱少了,B账户的钱就应该对应增加,这就转账成功了,如果A账户的钱少了,由于网络波动等因素转账失败了,B账户的钱没有增加,那么A账户就应该恢复成原先的状态

事务的四大特性

原子性:指的是一个事务应该是一个最小的无法分割的单元,不允许部分成功部分失败,只能同时成功,或者同时失败

持久性:一旦提交事务,那么数据就应该持久化,保证数据不会丢失

隔离性:两个事务修改同一个数据,必须按顺序执行,并且前一个事务如果未完成,那么中间状态对另一个事务不可见

一致性:要求任何写到数据库的数据都必须满足预先定义的规则,它基于其他三个特性实现的

InnoDB如何保证原子性和持久性的

通过undo log 保证事务的原子性,redo log保证事务的持久性

undo log是回滚日志,记录的是回滚需要的信息,redo log记录的是新数据的备份

当事务开始时,会先保存一个undo log,再执行修改,并保存一个redo log,最后再提交事务。如果系统崩溃数据保存失败了,可以根据redo log中的内容,从新恢复到最新状态,如果事务需要回滚,就根据undo log 回滚到之前的状态

事务并发问题有哪些

脏读:事务A读到了事务B修改还未提交的数据

幻读,也叫虚读:事务A两次读取相同条件的数据,两次查询到的数据条数不一致,是由于事务B再这两次查询中插入或删除了数据造成的

不可重复读:事务A两次读取相同条件的数据,结果读取出不同的结果,是由于事务B再这两次查询中修改了数据造成的

第一类丢失更新:也叫回滚丢失,事务A和事务B更新同一条数据,事务B先完成了修改,此时事务A异常终止,回滚后造成事务B的更新也丢失了

第二类丢失更新:也叫覆盖丢失,事务A和事务B更新同一条数据,事务B先完成了修改,事务A再次修改并提交,把事务B提交的数据给覆盖了

事务隔离级别有哪些,分别能解决什么问题

读未提交:事务读不阻塞其他事务的读和写,事务写阻塞其他事务的写但不阻塞读,能解决第一类丢失更新的问题,

读已提交:事务读不会阻塞其他事务读和写,事务写会阻塞其他事务的读和写,能解决第一类丢失更新,脏读的问题

可重复读:事务读会阻塞其他事务的写但不阻塞读,事务写会阻塞其他事务读和写,能解决第一类丢失更新,脏读,不可重复读,第二类丢失更新问题

串行化:使用表级锁,让事务一个一个的按顺序执行,能解决以上所有并发安全问题

MySql的InnoDB是如何保证原子性的

利用了undo log实现的

undo log记录了这些回滚需要的信息,当事务执行失败或调用了rollback,导致事务需要回滚,就可以利用undo log中的信息将数据回滚到修改之前的样子

MySql的InnoDB是如何保证持久性的

利用了redo log实现的

redo log记录的是新数据的备份,在事务提交前,需要将Redo Log持久化,当系统崩溃时,可以根据redo Log的内容,将所有数据恢复到最新的状态

说一下事务的执行流程(Undolog+Redolog)

假设有A=1,B=2,两个数据,现在有个事务把A修改为3,B修改为4,那么事务的执行流程:

当事务开始时,会首先记录A=1到undo log,记录A=3到redo log,和记录B=2到undo log,记录B=4到redo log,然后再将redo log写入磁盘,最终事务提交

解释一下事务并发丢失更新问题,·如何解决

第一类丢失更新:也叫回滚丢失,事务A和事务B更新同一条数据,事务B先完成了修改,此时事务A异常终止,回滚后造成事务B的更新也丢失了

第二类丢失更新:也叫覆盖丢失,事务A和事务B更新同一条数据,事务B先完成了修改,事务A再次修改并提交,把事务B提交的数据给覆盖了

SQL标准中的四种隔离级别,读未提交,读已提交,可重复读,串行化,都能解决第一类数据更新丢失问题

对于第二类丢失更新问题,可以使用悲观锁也就是串行化来解决,也可以使用乐观锁的方式,比如加一个版本号管理来解决

InnoDB事务隔离的实现原理是什么

隔离的实现主要利用了读写锁和MVCC机制

读写锁,要求在每次读操作时需要获取一个共享锁,写操作时需要获取一个写锁。共享锁之间不会产生互斥,共享锁和写锁,写锁与写锁之间会产生互斥。当产生锁竞争时,需要等一个操作的锁释放,另一个操作才能获得锁

MVCC,多版本并发控制,它是在读取数据时通过一种类似快照的方式将数据保存下来,不同的事务看到的快照版本是不一样的,即使其他事务修改了数据,但是对本事务仍然是不可见的,它只会看到第一次查询到的数据

可重复读是只在事务开始的时候生成一个当前事务全局性的快照,而读提交则是每次执行语句的时候都重新生成一次快照

数据库集群

Mysql主从解决什么问题,不能解决什么问题?

MySQL主从同步,主负责写,从负责读,使用一主多从,能减轻读的压力

但是这不能解决写的压力和主库的单点故障,如果主库的写并发高,可以做成多个主库

MySql主从复制原理?

主要依靠binlog来实现的,它记录的是所有的DDL,DML,TCL操作

当主库的数据发生改变时,会将改变记录保存到binlog中

从库新开一个线程将binlog内容发送到从库

从库会发起一个I/O线程请求主库的binlog,并保存到中继日志中

从库新开一个SQL线程,读取中继日志并解析成具体操作,从而将主库更新的内容写到了从库中

MySql主从配置步骤?

安装mySQL主从客户端,并配置my.ini

主库需要配置授权从库使用的账号和权限,启动后可以通过show 主库名 status查看状态,我们需要记录File和Position的值,File是对应的binlog文件名,position是当前同步数据的最新行

从库需要配置主库链接信息,包括账号密码和binlog文件名和最新行,然后启动。通过show 从库名 status 检查同步状态,Slave_IO_Running 和 Slave_SQL_Running 的值都为YES,说明大功告成了

什么是垂直分表,垂直分库,水平分表,水平分库

垂直分表,可以理解为按列分表,如果一个表的字段太多了,可以按照使用频率分成不同的表,优化查询性能。比如商品表可以分为商品类型表,商品详情表,商品促销表等等

垂直分库,为了减轻单个数据库压力,我们可以按照业务类型,拆分成多个数据库,比如分布式架构,不同的模块可以有不同的数据库

水平分表,可以理解为按行分表,如果一个表的数据有千万行,查询性能太低,可以拆分成10张小表,每张表保存一百万行数据

水平分库,我们做了水平分表后,表数量太多了也会影响数据库查询效率,我们可以将这些表分到多个数据库中

分库分表后会出现哪些问题?怎么解决

会产生分布式事务,以前本地事务就能结局的问题现在要用上Seata分布式事务

垂直分库后跨库查询会导致一个查询结果来源于两个库,可能要用到多线程调用多个库查询

水平分库后一个分页查询的某一页可能来自两个库,可以将两个库的数据合并之后再执行SQL

水平分表后不同的表出现主键重复,可以通过雪花算法来解决

两个库都用到同一个表,那这个公共表的维护可能要用到MySQL主从同步

你们公司使用的是什么技术来水平分表?还可以有什么技术?有什么区别?

使用的是sharding-jdbc来实现的,它是由java开发的关系型数据库中间件,读写分离,分库分表操作简单

TDDL,淘宝业务框架,复杂而且分库分表的部分还没有开源

Mycat,要安装额外的环境,不稳定用起来复杂

MySQL官方提供的中间件,不支持大数据量的分不分表,性能较差

你们使用什么规则来分库分表的?还有哪些规则?

垂直分库,按照业务进行垂直分库,比如课程表和用户表放到不同数据库

垂直分表,把多字段表拆分少量字段表,比如将课程表分为课程类型表,课程详情表,课程促销表等

水平分表,把海量数据表拆分为多个小表

把商品业务进行水平分库,可以对水平分库后每一个数据库服务器进行集群

你从哪些方面去优化你的数据库?

如果是并发高,可以考虑缓存,如果是数据量大可以考虑分库分表,具体如下:

首先应该考虑垂直分库,不同的业务使用不同的数据库

然后进行垂直分表,按照使用频率把字段多的表拆分成若干个表

对经常查询的列建立索引,提高查询效率

设计冗余字段,减少join表的次数

SQL优化,比如尽量使用索引查询

对热点数据应该考虑做缓存,比如首页展示汇总数据

从海量数据中查询数据应该考虑用全文检索

如果查询并发高,可以对mySQL做集群

如果数据量实在太大了,可以考虑水平分表,

水平分表后,表数量还是太多了,可以考虑水平分库

Mysql的集群有哪些模式?

一主一从;一主多从;双主;环形多主;级联同步

单机优化到极致了,可以怎么优化?

可以考虑做集群,比如一主多从模式,然后对应用做读写分离

多机优化有哪些方式?

分表,分库,主从同步

解释一下分库分表的含义?

垂直分表,可以理解为按列分表,如果一个表的字段太多了,可以按照使用频率分成不同的表,优化查询性能。比如商品表可以分为商品类型表,商品详情表,商品促销表等等

垂直分库,为了减轻单个数据库压力,我们可以按照业务类型,拆分成多个数据库,比如分布式架构,不同的模块可以有不同的数据库

水平分表,可以理解为按行分表,如果一个表的数据有千万行,查询性能太低,可以拆分成10张小表,每张表保存一百万行数据

水平分库,我们做了水平分表后,表数量太多了也会影响数据库查询效率,我们可以将这些表分到多个数据库中

水平分表有哪些分表规则?

按照区间范围分表,比如把用户按照年龄分为新生代表,青年代表,老年代表

按照时间分表,比如按照年来分表,比如登录日志,分成今年的表,去年的表。。

hash分表,通过将某一列的值比如id,通过一定的hash算法来算出对应那张表

雪花算法,通过雪花算法生成id,根据id来算出对应那张表

能简单说一下你怎么使用shardingjdbc做读写分离的嘛

首先导入相关的依赖

然后在配置文件中配置datasource,包括主从数据库的名字,主从数据库的连接信息,配置负载均衡

项目中就可以正常使用datasource了,自动做读写分离

能简单说一下你怎么使用shardingjdbc做读分库分表的嘛

首先,要改造数据库,比如水平分表,水平分库

在配置文件中,需要做如下配置

  • datasource名字,多个数据源就配多个datasource
  • 分库策略,比如按照哪一列分库,分库规则
  • 分表策略,比如哪些库下面的哪些表,按照那一列分表,分表规则
  • 配置公共的表

然后项目中就可以正常使用了

你可能感兴趣的:(《找工作再也不愁》,数据库,mysql,面试)