java面经 MySQL

存储引擎--MyISAM和InnoDB的区别

使用场景

对比 java面经 MySQL_第1张图片

MySQL隔离级别--未提交读,提交读,可重复读,序列化

 隔离级别含义

隔离级别

英文名称

含义

脏读

复读

幻读

未提交读

READ UNCOMMITTED

可读取其它事务未提交的结果

提交读

READ COMMITTED

一个事务开始时,只能读到其他事务已经提交的修改。

例:如果A事务已经修改了XX,但还没提交,则B事务读XX时还是未修改的值。

Oracle等多数数据库默认是该级别)。

×

可重复读

REPEATABLE READ

在开启事务时,同一条件的查询返回的结果是一样的。

例:A事务开启,查询一条记录;B事务更新这条记录并提交,A事务再次查询这条记录(查到的结果跟第一次查到的一样,而不是B修改过的结果)。

MySQL默认级别

×

×

可序列化

SERIALIZABLE

 

当一个事务执行时,会对所涉及的数据行进行加锁,其他事务无法对这些数据行进行修改或读取,直到当前事务提交或回滚。

×

×

×

脏读、不可重复读、幻读的含义

java面经 MySQL_第2张图片

      

索引的分类

java面经 MySQL_第3张图片

java面经 MySQL_第4张图片

索引的优点/缺点

优点

索引优点就是提高了查询性能,主要是以下几个方面

  1. 索引大大减少了服务器需要扫描的数据量。
  2. 索引可以帮助服务器避免排序和临时表。
  3. 索引可以将随机I/O 变为顺序I/O

缺点

  1. 降低了数据写入的效率。原因:当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护
  2. 索引增加了查询优化器的选择时间。查询优化器在对一条sql语句进行分析时,会结合一系列的分析计算出一条最优的查询sql。添加了索引之后,相当于是在原来的基础上,添加了对索引因素的分析,若在很多字段上创建了索引,会增加这个选择的时间。
  3. 索引占物理空间。除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。

创建索引的原则

索引原则

说明/示例

对查询频率高的字段创建索引

        查询频率高的字段有:作为查询条件的字段(where子句中的列)、连接子句中指定的列

为经常需要排序、分组和联合操作的字段建立索引

经常需要ORDER BY、GROUP BY、DISTINCT和UNION等操作的字段,排序操作会浪费很多时间。

        如果为其建立索引,可以有效地避免排序操作。

尽量使用唯一索引

          唯一性索引的值是唯一的,可以更快速的通过该索引来确定某条记录。  唯一性索引的值是唯一的,可以更快速的通过该索引来确定某条记录。

使用短索引

          如果索引的值很长,那么查询的速度会受到影响。例如,对一个CHAR(100)类型的字段进行全文检索需要的时间肯定要比对CHAR(10)类型的字段需要的时间要多。

使用前缀来索引

        如果索引字段的值很长,最好使用值的前缀来索引。例如,TEXT和BLOG类型的字段,进行全文检索会很浪费时间。如果只检索字段的前面的若干个字符,这样可以提高检索速度。

索引的数目不要太多

过多的索引会导致insert、update、delete语句的执行效率降低;

每创建一个索引都会占用相应的物理空间;

对查询频率高的字段创建索引

        查询频率高的字段有:作为查询条件的字段(where子句中的列)、连接子句中指定的列

对查询频率高的字段创建索引

        查询频率高的字段有:作为查询条件的字段(where子句中的列)、连接子句中指定的列

java面经 MySQL_第5张图片

索引失效的原因/解决方案java面经 MySQL_第6张图片

java面经 MySQL_第7张图片

java面经 MySQL_第8张图片

java面经 MySQL_第9张图片

java面经 MySQL_第10张图片

java面经 MySQL_第11张图片

联合索引--使用/原理/优化java面经 MySQL_第12张图片

java面经 MySQL_第13张图片

使用联合索引可以做到覆盖索引,从而避免会表查询。举个例子,从user表中查询用户id,姓名和性别,查询条件为姓名,这时候就可以对用户姓名和性别创建联合索引,这样可以做到覆盖查询和避免会表查询。

另一个场景是,如果存在多个查询条件,针对于查询字段建立联合索引,可以提高多个查询条件组合的查询性能。

索引的优化--LIKE模糊查询java面经 MySQL_第14张图片

聚集索引/辅助索引/回表查询/覆盖索引

回表查询,先查询辅组索引,再查询聚集索引。

覆盖索引,只用查询辅组索引或者聚集索引。

尽量将回表查询转换为覆盖查询,转换的方法为对要查询的字段建立联合索引,从而避免回表查询。

分库分表--垂直分表与水平分表

垂直(纵向)切分

垂直分库就是根据业务耦合性,将关联度低的不同表存储在不同的数据库,如下图。java面经 MySQL_第15张图片

 

垂直分表是基于数据库中的"列"进行,某个表字段较多,可以新建一张扩展表,将不经常用或字段长度较大的字段拆分出去到扩展表中。

在字段很多的情况下(例如一个大表有100多个字段),通过"大表拆小表",更便于开发与维护,也能避免跨页问题,MySQL底层是通过数据页存储的,一条记录占用空间过大会导致跨页,造成额外的性能开销。

另外数据库以行为单位将数据加载到内存中,这样表中字段长度较短且访问频率较高,内存能加载更多的数据,命中率更高,减少了磁盘IO,从而提升了数据库性能。如下图。java面经 MySQL_第16张图片

 

优缺点
优点:

解决业务系统层面的耦合,业务清晰
与微服务的治理类似,也能对不同业务的数据进行分级管理、维护、监控、扩展等
高并发场景下,垂直切分一定程度的提升IO、数据库连接数、单机硬件资源的瓶颈

缺点:

部分表无法join,只能通过接口聚合方式解决,提升了开发的复杂度
分布式事务处理复杂
依然存在单表数据量过大的问题(需要水平切分)

水平(横向)切分

  • 切分时机:当一个应用难以再细粒度的垂直切分,或切分后数据量行数巨大,存在单库读写、存储性能瓶颈,这时候就需要进行水平切分了。
  • 分类:水平切分分为库内分表分库分表,是根据表内数据内在的逻辑关系,将同一个表按不同的条件分散到多个数据库或多个表中,每个表中只包含一部分数据,从而使得单个表的数据量变小,达到分布式的效果。库内分表只解决了单一表数据量过大的问题,但没有将表分布到不同机器的库上,因此对于减轻MySQL数据库的压力来说,帮助不是很大,大家还是竞争同一个物理机的CPU、内存、网络IO,最好通过分库分表来解决。
  • java面经 MySQL_第17张图片

优缺点

水平分库优点

  • 不存在单库数据量过大、高并发的性能瓶颈,提升系统稳定性和负载能力
  • 应用端改造较小,不需要拆分业务模块

水平分库缺点

  • 跨分片的事务一致性难以保证

  • 跨库的join关联查询性能较差

  • 数据多次扩展难度和维护量极大

 分片规则

  1. 取余/取模
    1. 均匀存放数据
    2. 缺点: 不能扩容
  2. 按照数量范围
    1. 1-500万      501万-1000万
  3. 按照日期范围
    1. 日志 ,订单信息,统计
  4. 按照月份
  5. 按照枚举值
    1. 常量
  6. 二进制取模范围
    1. 类似HashMap
    2. 缺点:数据存放不均匀
  7. 一致性hash分片           

典型的数据分片规则

1、根据数值范围

按照时间区间或ID区间来切分。例如:将userId为1~9999的记录分到第一个库,10000~20000的分到第二个库,以此类推。

优点

  1. 单表大小可控
  2. 天然便于水平扩展,后期如果想对整个分片集群扩容时,只需要添加节点即可,无需对其他分片的数据进行迁移
  3. 使用分片字段进行范围查找时,连续分片可快速定位分片进行快速查询,有效避免跨分片查询的问题。

缺点

热点数据成为性能瓶颈。连续分片可能存在数据热点,例如按时间字段分片,有些分片存储最近时间段内的数据,可能会被频繁的读写,而有些分片存储的历史数据,则很少被查询

2、根据数值取模

一般采用hash取模mod的切分方式,例如:将 Customer 表根据 id字段的hash值取模的余数切分到各个库中。这样同一个用户的数据会分散到同一个库中,如果查询条件带有id字段,则可明确定位到相应库去查询。

优点:数据分片相对比较均匀,不容易出现热点和并发访问的瓶颈。

缺点:

1、后期分片集群扩容时,需要迁移旧的数据。
2、容易面临跨分片查询的复杂问题。比如上例中,如果频繁用到的查询条件中不带id时,将会导致无法定位数据库,从而需要同时向4个库发起查询,分库反而成为拖累。

 

 

 

你可能感兴趣的:(Java面经,java,mysql,数据库)