Java进阶笔记(持续更新~)
目录📐
- 一.MySQL
- 1.执行一条SQL的过程
- (A)连接器
- (B)缓存
- (C)分析器
- (D)优化器
- (E)执行器
- 2.MySQL引擎的区别
- (A)MyISAM:不支持事务 操作表数据锁表
- (B)InnoDB: 支持事务 操作表数据锁行
- 3.数据库优化思路
- (A)SQL语句优化
- (B)索引优化
- (C)数据库结构优化
- (D)服务器硬件优化
- 1.执行一条SQL的过程
- 二.JVM
- Java类的加载过程
- (A)加载(将class文件转换成class实例)
- (B)验证 (验证类数据信息是否符合JVM规范)
- (a)格式检查:魔数验证,版本检查,长度检查
- (b)语义检查:是否继承final,是否有父类,是否实现抽象方法
- (c)字节码验证:跳转指令是否指向正确的位置,操作数类型是否合理
- (d)符号引用验证:符号引用的直接引用是否存在
- (C)准备 (分配静态变量的内存空间)
- (D)解析(将常量池中的符号引用转为直接引用)
- (E)初始化 (加载start块和给start变量赋值)
- Java类的加载过程
- Java运行时数据区结构
- (A)PC寄存器/程序计数器(每个线程有一个独立的程序计数器,且互不影响,独立储存)
- (a)保存当前正在执行的程序的内存地址。
- (B)Java栈 Java Stack(每条线程对应一个栈,一个栈中对应多个栈帧,执行一个方法压入一个栈帧,结束一个方法出一个栈帧)
- (a)栈帧是每个方法关联起来的,每运行一个方法就创建一个栈帧,每个栈帧会含有一些局部变量,每当一个方法执行完成时,该栈帧就会弹出这个栈帧的元素作为这个方法的返回值,并清除这个栈帧。
- (b)Java栈顶的栈帧就是当前执行的活动栈,也就是正在执行的方法,
PC寄存器会指向该地址
。 - (c)栈帧的结构:
局部变量表,操作数栈,动态连接方法,返回的地址
- (C)堆 Heap(堆时JVM所管理的内存中最大的一块,被所有的Java线程锁共享,不是线程安全的,在JVM启动时创建)
- (a)所有对象实例以及数组都要在堆上分配。
- (b)Java堆时GC管理的主要区域,现在GC基本都采用
分代收集算法
,所有堆还可以细分为:新生代和老年代
新生代再细致一点有Eden空间,From Survivor空间,To Survivor空间
等。
- (D)方法区Method Area(方法区存放了要加载类的信息(名称,修饰符等)类中定义为静态常量,类中的Field信息,类中的方法信息,
方法区是被Java线程共享的
)- (a)方法区数据虽然时被线程共享,但是不会像Java堆一样被GC频繁回收,它储存的信息相对比较稳定,再一定条件下会被GC
- (E)常量池Constant Pool(
常量池本身是方法区的一个数据结构。
)- (a)常量池中储存了如字符串,final变量值,类名和方法名变量值。常量池在编译期间就被确定,并保存在已编译的。class文件中。
- (F)本地方法栈Native Method Stack(本地方法栈和Java栈所发挥的作用非常相似,区别不过是Java栈为JVM执行Java方法服务,而本地方法栈为JVM执行Native方法服务。本地方法栈也会抛出StackOverflowError和OutOfMemoryError异常。)
- (A)PC寄存器/程序计数器(每个线程有一个独立的程序计数器,且互不影响,独立储存)
- JMM
- 三.Hadoop
- 1.区分hdfs hbase hive 区别以及应用场景
- 四.Redis
- 五.MQ
- 六.微服务
🍃MySql
一,执行一条SQL的过程
1.连接器和客户端建立连接
- 验证账号密码 -> 账号不对,报错:“Access denied for user”
- 认证通过,在权限表中查询拥有的权限
1.在连接过程才会从权限表中读取权限信息,中途对权限更新不会影响已经建立的连接
2.若规定时间内无活动,则自动会断开连接。规定时间由wait_timeout
控制,默认为8个小时
优化:防止数据库中出现占用大量内存的情况,可以用:
1.定期断开长连接或者占用内存过大的连接。
2.MySQL5.7以上的版本,每次执行一个较大的操作,可执行mysql_reset_connection
命令来初始化连接资源,该操作不会重连和重新获取授权,只是恢复到刚建立连接的状态。
2. 查询缓存(MySQL8.0后将删除该功能)
- 之前执行的过的语句,会以语句为Key,执行后的结果集为Value储存在内存中。
- 如果缓存命中,则直接返回结果
- 如果缓存没有命中,则继续执行,并且将语句和结果集以key-value的形式存于内存。
1.只要更新表,将会把该表缓存全部清空(缓存适用于不常更新的静态表)
优化:
1.设置默认为不适用缓存,只针对不常用的静态表指定使用缓存(将query_cache_type 设置为 DEMAND,默认SQL不使用查询缓存)
select SQL_CACHE * from T where ID = 10;
3.分析器
- 1.词法分析
识别SQL关键字,提出主要成分。MySQL根据select
得出这是一条查询语句,根据from T
识别表,将ID
识别为列名。 - 2.语法分析
根据语法规则判断是否符合SQL的语法。如果出现错误,则提示:You have an error in your SQL syntax...
后面是错误的地方,需要你关注use naer
后的内容。
4.优化器
- 选取最优的执行方式:
1.当涉及到多个索引时,决定用哪个索引
2.多表关联时,决定连接顺序
select * from t1 join t2 using(ID) where t1.c=10 and t2.d=20;
该步骤决定了先从t1表中取出`c=10`的ID值还是先查找出t2表中`d=20`的ID值。
5.执行器
- 1.根据连接器取到权限,判断该用户是否对T表有权限。
- 2.若有权限,继续打开表继续操作。
打开表后,根据表的引擎定义,使用提供的接口解析数据:- 表T中ID字段无索引:
1. 调用InnoDB提供的接口,取出第一行,ID=10
时,将该行数据放入结果集。不符合则再次调用引擎接口获取下一行,再次判断,直到执行完最后一行。
2. 将结果集存入缓存,返回给客户端。 - 表T中的ID字段有索引:
1. 调用InnoDB的索引方法获取满足条件的第一行
接口,server层还会再判断一次值是否正确,然后放入结果集,接着继续访问满足条件的下一行
接口,这些结构时引擎已经定义好的。其原理是使用B+tree。
- 表T中ID字段无索引:
问题:
- 如果在查询语句中的字段不存在,会在哪个阶段报错?
分析器阶段。 - MySQL中解析器和预处理器有什么作用?
解析器:处理语法啊和解析查询,生成一颗对应的解析树。
预处理器:进一步检查解析树的合法性,比如:数据表和数据列是否存在,别名是否有歧义等。如果通过则生成新的解析树,再提交给优化器。 - Connect_timeout和wait_timeout是指什么?
Connect_timeout :连接过程中的等待时间。
wait_timeout:连接完成后,使用过程中的等待时间。
二,MySQL引擎的区别
MySQL有四种引擎:ISAM , MyISAM,HEAP,InnoDB
ISAM :ISAM执行读取操作的速度很快,不支持事务处理,也不能够容错。
MyISAM:MyISAM是MySQL的ISAM扩展格式和缺省的数据库引擎。
HEAP:HEAP允许只驻留在内存里的临时表格。驻留在内存里让HEAP要比ISAM和MYISAM都快。
InnoDB:支持事务等高级操作。
- MySQL5.1之前默认引擎是MyISAM,MySQL5.1之后默认引擎改为InnoDB
InnoDB支持事务并且更新数据是行锁,MyISAM不支持事务更新数据是表锁
MyISAM数据文件比InnoDB多出一种索引文件,MyISAM比InnoDB的查询速度块很多。
三,数据库优化思路
1.SQL语句优化:
- 尽量避免放弃使用索引而引起全表扫描,例如:
- where子句中使用!=
- where子句中使用<>
- where子句中改变=号左边的值
- where子句中对字段进行null值判断 is null
select id from user where num is null
- 优化建议:
- 将为null的值由0代替
select id from user where num = 0
- 很多时候使用exists代替in是一个好的选择
- 用where子句替换having子句因为having只会在检索出所有记录之后才会对结果集进行过滤
- 将为null的值由0代替
2.索引优化
- 在具有这些性质的字段上建立索引:
- 经常搜索(可以加快搜索速度)
- 作为主键的列,强制该列的唯一性和组织表中的排序结构
- 在经常用于连接的列上(外键,可以加快连接速度)
- 在经常需要根据范围进行搜索的列上(索引以及排序,指定范围是连续的)
- 在经常需要排序的字段
- 在经常使用where的列上(加快条件的判断速度)
- 不应该建立索引列的特征:
- 查询中很少使用或者参考的列
- 数据值很少的列,例如:性别
- 类型定义为text,image和bit数据类型的列
- 修改远远大于检索的列
3.数据库结构优化
- 范式优化:
- 消除沉余(节省空间)
- 反范式优化:
- 适当加沉余(减少join)
- 拆分表:
- 分区将在物理硬盘上分割开,不同分区的数据可以制定保存在处于不同磁盘的数据文件里。当对这个表查询时,只需要在表分区中进行扫描,而不必进行全表扫描,另外处于不同磁盘的分区也将对这个表的数据传输分散在不同的磁盘I/O,一个良好的分区可以将数据传输对磁盘I/O竞争均匀地分散开。对数据量大的时候可采用此方法。
- 例:1.产品表(数据量10万,稳定),2.订单表(数据量200万,且有增长趋势)3.用户表(数据量100万,且有增长趋势)
- 垂直拆分
- 方案:吧产品表和用户表放在一个server上订单表单独放到一个server上
- 解决问题:表于表之间的io竞争
- 不解决的问题:单表中数据量增加出现的压力
- 水平拆分
- 方案:用户表通过性别拆分男用户和女用户,订单表通过已完成订单和未完成订单拆分,将未完成数据单独放在一个server上,已完成订单和男用户放在一个server上
- 解决问题:单表中数据量增加出现的压力
- 不解决的问题:表与表之间的io争夺
4.服务器硬件的优化
- 花钱扩展服务器性能,搭建集群等等
🍃JVM
Java类的加载过程
- 类从被加载到JVM中开始,到卸载为止,整个生命周期包括:
加载
、验证
、准备
、解析
、初始化
、使用
和卸载
七个阶段。 - 其中类加载过程包括
加载
、验证
、准备
、解析
和初始化
五个阶段。
加载(将Class文件转换成Class对象实例)
- 1.类加载器根据一个类的全限定名来读取此类的二进制字节流到JVM中,然后转换为一个与类目标对应的java.lang.Class对象实例。
- ①BootstrapClassLoader:负责加载$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类。
- ②ExtClassLoader:负责加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包。
- ③AppClassLoader:负责加载ClassPath中指定的jar包及目录中的class
- ④CustomClassLoader:属于应用程序根据自身需要自定义的ClassLoader,如tomcat,Jboss都会根据j2ee规范自行实现ClassLoader。
- defineClass方法将字节码的byte数组转换为一个类的class对象实例,如果希望在类被加载到JVM时就被链接,可以在自定义类加载器中调用resolve'Class方法。
-
自定义类加载器需要继承抽象类ClassLoader,实现findClass方法,该方法会在lodClass调用的时候被调用,findClass默认会抛出异常。
- findClass:表示根据类名查找类对象。
- loadClass:表示根据类名进行双亲委派模型进行类加载并返回类对象。
- defineClass:表示根据类的字节码转换为类对象。
-
自定义类加载器需要继承抽象类ClassLoader,实现findClass方法,该方法会在lodClass调用的时候被调用,findClass默认会抛出异常。
验证(验证数信息是否符合JVM规范,是否是一个有效的字节码文件)
- 验证内容:
类数据信息的格式验证,语义分析,操作验证
等。- 格式验证:
验证是否符合class文件规范
- 语义验证:
检查一个被标记为final的类型是否包含子类;检查一个类中的final方法视频被子类进行重写;确保父类和子类之间没有不兼容的一些方法声明(比如方法签名相同,但方法的返回值不同)
- 操作验证:
在操作数栈中的数据必须进行正确的操作,对常量池中的各种符号引用执行验证(通常在解析阶段执行,检查是否通过富豪引用中描述的全局定名定位到指定类型上,以及类成员信息的访问修饰符)
- 格式验证:
准备(为类追踪的所有静态变量分配内存空间,并为其设置一个初始值(由于还没产生对象,实例变量不在此操作范围内))
- 被final修饰的静态变量,会直接赋予原值。
- 类字段的字段属性表中存在ConstantValue属性,则在准备阶段,其值就是ConstantValue的值。
解析(将常量池中的符号引用转为直接引用(得到类或者字段,方法在内存中的指针或者偏移量,一遍直接调用该方法,这个可以在初始化之后再执行))
- 可以认为是一些静态绑定的会被解析,动态绑定则只会在运行时进行解析。
- 静态绑定包括一些final方法(不可重写),static方法(只属于当前类),构造器(不会被重写)
初始化(将一个类中所有被static关键字表示得代码统一执行一遍)
- 如果执行得是静态变量,那么就会使用用户指定得值覆盖之前在准备阶段设置得初始值
- 如果执行得是static代码块,那么在初始化阶段,JVM就会执行static代码块中定义的所有操作。
- 所有类变量初始化语句和静态代码块都会在编译时被前端编译器放在收集器里头,存放到一个特殊的方法中,这个方法就是<clinit>方法,即类/接口初始化方法。该方法的作用就是初始化一个中的变量,使用用户指定的值覆盖之前在准备阶段里设定的初始值,任何invoke之类的字节码都无法调用<clinit>方法,由JVM负责保证一个类的<clinit>方法执行之前,它的父类<clinit>方法已经被执行。
- JVM必须确保一个类在初始化的过程中,如果多线程需要同时初始化它,仅仅只能允许其中一个线程对其执行操作,其余线程必须等待,只有在活动线程执行完对类的初始化操作之后,菜会通知正在等待的其他线程。
Java运行时数据区结构
- (A)PC寄存器/程序计数器(每个线程有一个独立的程序计数器,且互不影响,独立储存)
- (a)保存当前正在执行的程序的内存地址。
- (B)Java栈 Java Stack(每条线程对应一个栈,一个栈中对应多个栈帧,执行一个方法压入一个栈帧,结束一个方法出一个栈帧)
- ![](https://img.haomeiwen.com/i14037200/6f9066f05140f0ef.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
- (a)栈帧是每个方法关联起来的,每运行一个方法就创建一个栈帧,每个栈帧会含有一些局部变量,每当一个方法执行完成时,该栈帧就会弹出这个栈帧的元素作为这个方法的返回值,并清除这个栈帧。
- (b)Java栈顶的栈帧就是当前执行的活动栈,也就是正在执行的方法,`PC寄存器会指向该地址`。
- (c)栈帧的结构:`局部变量表,操作数栈,动态连接方法,返回的地址`
- (C)堆 Heap(堆时JVM所管理的内存中最大的一块,被所有的Java线程锁共享,不是线程安全的,在JVM启动时创建)
- (a)所有对象实例以及数组都要在堆上分配。
- (b)Java堆时GC管理的主要区域,现在GC基本都采用`分代收集算法`,所有堆还可以细分为:`新生代和老年代`新生代再细致一点有`Eden空间,From Survivor空间,To Survivor空间`等。
- (D)方法区Method Area(方法区存放了要加载类的信息(名称,修饰符等)类中定义为静态常量,类中的Field信息,类中的方法信息,`方法区是被Java线程共享的`)
- (a)方法区数据虽然时被线程共享,但是不会像Java堆一样被GC频繁回收,它储存的信息相对比较稳定,再一定条件下会被GC
- (E)常量池Constant Pool(`常量池本身是方法区的一个数据结构。`)
- (a)常量池中储存了如字符串,final变量值,类名和方法名变量值。常量池在编译期间就被确定,并保存在已编译的。class文件中。
- (F)本地方法栈Native Method Stack(本地方法栈和Java栈所发挥的作用非常相似,区别不过是Java栈为JVM执行Java方法服务,而本地方法栈为JVM执行Native方法服务。本地方法栈也会抛出StackOverflowError和OutOfMemoryError异常。)
🍃Hadoop
区分hdfs hbase hive 区别以及应用场景
Hive
Hive在Hadoop中扮演数据仓库的角色。建立在Hadoop集群的最顶层,对存储在Hadoop群上的数据提供类SQL的接口进行操作。你可以用HiveQL进行selelct,join等等操作。
特点:支持SQL查询
注意:Hive现在适合再离线下进行数据操作,不使用于在线查询,因为一个字“慢”
适用场景:不想用程序语言开发MapReduce的朋友们,熟悉SQL的朋友可以使用Hive开离线进行数据处理分析工作。如果你有数据仓库的需求并且你擅长写SQL并且不想写MapReduce jobs就可以用Hive代替。
HBase
HBase是一个数据库,一个NoSql数据库,像其他数据库一样提供随即读写功能,Hadoop不能满足于实时需要,HBase正可以满足。
特点:即时读写
适用场景:需要实时访问一些数据,就可以把它存入HBase,你也可以用Hadoop作为静态数据仓库,HBase作为数据存储,放那些进行一些操作会改变的数据。
问题:
什么情况下应用HBase?
- 1.成熟的数据分析主题,查询模式已经确立,并且不会轻易改变。
- 2.传统的关系型数据库已经无法承受负荷,高速插入,大量存取。
- 3.适合海量的,但同时也是简单的操作(例如 key-value)。
官方解释
Use Apache HBase™ when you need random, realtime read/write access to your Big Data. This project's goal is the hosting of very large tables -- billions of rows X millions of columns -- atop clusters of commodity hardware. Apache HBase is an open-source, distributed, versioned, non-relational database modeled after Google's Bigtable: A Distributed Storage System for Structured Data by Chang et al. Just as Bigtable leverages the distributed data storage provided by the Google File System, Apache HBase provides Bigtable-like capabilities on top of Hadoop and HDFS.
Pig VS Hive
Hive更适合于数据仓库的任务,Hive主要用于静态的结构以及需要经常分析的工作,Hive于SQL相似促使其成为Hadoop与其他BI工具结合的理想交集。
Pig赋予开发人员在大数据集领域更多的灵活性,并允许开发简介的脚本用于转换数据流以便潜入到较大的应用程序。
Pig相比Hive轻量,它主要的优势时相比于直接使用Hadoop Java APIs可大幅削减代码量。正因如此,Pig仍然是吸引大量的软件开发人员。
Hive和Pig都可以与HBase组合使用,Hive和Pig还为HBase提供了高层语言支持,使得在HBase上进行数据统计处理变的非常简单。
Hive VS HBase
Hive 是建立在Hadoop之上为了减少MapReduce jobs编写工作的批处理程序,HBases是为了支持弥补Hadoop对实时操作的缺陷弥补的项目。
想象你在操作RMDB数据库,如果是全表扫描,就用Hive+Hadoop,如果索引访问,就用HBase+Hadoop。
Hive query就是MapReduce jobs 可以从5分钟到数小时不止,HBase是非常高效的,肯定比Hive高效的多。
JDBC
未完待续~
文中有错误希望大家在评论区指出,谢谢~~~~~~~~~