jdk自带功能注意结果精度
ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
ScriptEngine scriptEngine = scriptEngineManager.getEngineByName("nashorn");
String str = "((10*0.8)/2-100)*-3";
Object eval = null;
try {
eval = scriptEngine.eval(str);
} catch (ScriptException e) {
e.printStackTrace();
}
System.out.println("=============");
System.out.println("old:"+ str + "=" + eval);
System.out.println("=============");
## 按字段汇总数据
matList = matList.stream().collect(Collectors.toMap(AirGoodsCountForm::getTabId, Function.identity(),
(a, b) -> {
Long count = a.getCount();
Long count1 = b.getCount();
a.setCount(count + count1);
return a;
})).values().stream().collect(Collectors.toList());
## 按字段分组数据
### 每个list数据的唯一
Map airGoodsCensusFormMap = matList.parallelStream()
.collect(
Collectors.toMap(AirGoodsCensusForm::getTabId, (p) -> p));
### 每个list数据的重复
Map> parentHouseData = airMaterials.stream().collect(Collectors.groupingBy(AirHouseListVo::getTabId));
# jvm
在执行java代码时指定jvm运行模式
JVM的三种运行模式
-Xint 纯字节码解释器(1)
-Xcomp 纯模板解释器(2)
-Xmixed 字节码解释器 + 模板解释器(3)
例如: java -showversion -Xint -jar xxx.jar showversion表示显示jvm运行模式
## jvm 分区
程序计数器------------------------->线程私有
java虚拟机栈------------------------->线程私有
本地方法栈------------------------->线程私有
java堆------------------------->线程公有
方法区------------------------->线程公有
## JVM内存分配
1.栈内存分配
保存参数、局部变量、中间计算过程和其他数据。退出方法的时候,修改栈顶指针就可以把栈帧中的内存销毁。
栈的优点:存取速度快,仅次于寄存器,栈数据可以共享。
栈的缺点:存在栈中的数据大小、生存期是在编译时确定的,导致其缺乏灵活性。
2.堆内存分配
堆的优点:
动态地分配内存大小,生存期不必事先告诉编辑器,他在运行期动态分配的,垃圾回收器会自动收走不再使用的空间区域。
堆的缺点:
运行时动态分配内存,在分配和销毁时都要占用时间,因此堆的效率较低。
# redis如何保证高可用
redis 如何删除过期 - 定时删除(redis特定的算法) 惰性删除(查询发现过期删除) 内存淘汰()
缓存击穿 缓存穿透 缓存雪崩 - 过期时间平均分配 热点数据永不删除
AOF策略 记录操作日志
集群(3)+主从复制(3)
-----------------
主要来源b战的up---本人学习记录笔记
连接模块 -- 连接池 --连接驱动
sql接口-- sql解析器-- sql优化器--缓存
存储引擎--(InnoDB-5.7常用默认,myISAM,Cluster,Fanlcon)
InnoDB:
sql语句--->执行计划--->正常
--->执行缓存器(buffer pool[页--记录数据])--->磁盘
--->(读)自适应哈希索引(有数据读取 没有磁盘读取并追加到热点页) 索引 数据
---> free链表 flush链表 LRU链表 管理数据页的写入位置 刷盘位置 数据页淘汰
--->写
--->undo buffer ---> .idu 表空间
--->redo log buffer ---> redo log (断电恢复数据)中 --->.idu 表空间--->最后写入 buffer pool 中/change buff 然后合并---->buffer pool 中--->写入 double write buff --->系统表空间
--->独立表空间.idb
--->异常--->redo log buffer---------->page cache(操作系统io)--->磁盘
表---->t.frm(表结构等信息)
---->t.ibd(表空间--存储数据和索引和碎片区)
--->页<=16k(默认6个页[在碎片区--最多32个页])--(页头,数据行[变长列表,null列表,记录头,列值1,列值2....]<=8K,页尾)--相近的页查询会比较快---机械硬盘磁盘位置相邻---跨页查询会导致机械硬盘寻找磁道时间变长导致查询变慢
--->段(逻辑)---页(b+树索引根[非叶子节点段])+区([叶子节点段])==表空间idb文件
--->区=1m(64个连续页)--优化磁头查询时间
--->区组=256m(256区---第一个区[比较特殊])
--->buffer pool(多个区组 )
sql语句 --->连接池(半双工通信)
--->缓存(map
)--不常用(命中率较低--建立缓存慢) --->sql解析器(词法分析-语法分析)
--->预处理器
--->sql优化器(优化成本分析轨迹打开 查看成本 查看之后记得关闭要不然会有性能问题)
SHOW STATUS LIKE ‘last_query_cast’ (子查询 和 union 无法计算)
查看最近sql语句消耗的成本(io cost + cpu cost)
--->执行器(sql优化器发送执行计划)
--->存储引擎 调用Handler Api 执行计划 (索引查询 遍历查询 零时表 在存储引擎执行)
--->通过Tcp协议讲结果集返回给客户端(如果开启了查询缓存会更新查询缓存 反而影响性能)
### 11种不同类型的页
一个数据块4个页 校验页的完整性校验算法crc32验证--默认
页头 file header 38个字节
---->校验和
---->页号 4个字节
---->上页号
---->下页号 双向链表
---->最近被修改的LSN
---->页类型
---->已被刷到磁盘的LSN
---->表空间id
数据页 索引页
---->数据行 对应真实数据
record_type:
0:业务数据,普通记录。
1:B+树的非叶子节点(本文暂时还没用到)。
2:最小记录。
3:最大记录。
默认创建新页时默认创建
---->一个行类型record_type为2的最小行
---->一个行类型record_type为3的最大行
---->不做任何存储作为链表的头和尾使用
----> DYNAMIC 切分为2半
---->额外信息
---->变长字段长度列表
---->null值列表
---->头信息(40bit)
--->删除标记
--->非页节点最小标记
--->目录组内行数
--->行在页内的位置
--->行类型
--->下一行的地址偏移量(指下一行数据的起始地址)
---->真实数据 主键值 列1的值 列2的值
页尾 file trailer 8个字节
---->校验和
---->最近被修改的LSN
## mysql索引原理
读取4kb的磁盘寻址读写:随机io,连续io,
由于磁盘读取缓慢,所以每次读取4*4kb存放入内存中 成为数据页
b+树的节点--->加载到buffpool
--->树的头就是每个页中最小行的主键--是上一个页最大行的主键\
--->就这样连接起来了
--->树的尾就是每个页中最大行的主键--是下一个页最小行的主键/
--->聚族索引和非聚族索引
## 如何查看索引
使用explan工具查看
主要列有
性能 | type | 场景 | sql |
---|---|---|---|
1 | system | 不存在iondb中 | |
2 | const | 最快有且只有一行 | |
3 | eq_ref | 连表主键查询出现 | |
4 | ref | 二级索引查询时不使用主键查询或者唯一非空索引 | |
5 | ref_or_null | 二级索引查询时不使用主键查询或者唯一非空索引 | |
6 | index_merge | 想多个搜索合并为一个 | |
7 | range | 不是等值查询时 BETWEEN,LIKE,IN,大于,小于,等,要对索引树扫描效率并不高 |
|
8 | index | 查询结果集包含缩影就会出现,效率和all一样, 条件字段没有索引 |
|
9 | all | 查询结果集包含全部字段,条件字段没有索引 | |
性能 | extra | 场景 | sq |
1 | using index | 无语聚族缩影查询,无需回表查询 | |
2 | using index condition | 有二级索引查询,需需回表查询 | |
3 | using where | 查询条件任意字段,不走索引 一定要优化 |
|
4 | using MRR | 有二级索引作为条件时对二级索引缓存进行排序,一般不会出现除非设置 | |
5 | using join buffer | 关联查询,如果a的age有索引但是b的age没有索引,会全表扫描a循环关联b,不建议使用 | |
6 | using union | 多个查询条件都是索引会对查询条件进行合并 | |
7 | using temporary | 进行分组查询且分组条件字段为索引字段,记住一定在对该字段加索引 | |
8 | using filessort | 查询条件为任意索引字段之后在进行排序, 可以通过讲查询字段和排序字段新建组合索引就不用再次排序 |
|
------分割线------
事务
(InnoDB 引事务
事务
原子性,一致性,隔离性,持久性
一致性 是老大 其他 3个为一致性服务
手动事务
开启事务
start transaction;
sql 1;
sql 2;
提交事务
commit;
自动事务
set autocommit = 'no' --自动提交事务
原子性:
通常一条sql 一条undolog日志,更新操作会有2条,出现错误时回滚 一批undolog日志
撤销日志 (undo log)
undo log 日志结构
file header | ||
undo page header (用来连接多个undo age 使用链表链接) | ||
undo log segment header | ||
undo log header | ||
undo1 | undo2 | undo3 |
type-insert | type-delete | type-update |
表id | 表id | 表id |
..... | ..... | ..... |
common信息 | common信息 | common信息 |
主键信息 | 旧事物id 旧roll_pointer 主键信息 |
旧事物id 旧roll_pointer 主键信息 被更新信息 |
file trailer |
真实数据会有 roll_pointer与undo log的roll_poiner 关联 多个 undo log 也通过 roll_pointer关系
每条数据会有undo log 的版本链,回滚的时候可以依次撤销
1个undo log(回滚日志)存放 ---- 128个undo log segment(回滚日志段)
1个undo log segment(回滚日志段) ---- 存放 1024个undo log page页
执行器--->undo log 记录着回滚前的数据
锁
锁信息
基本信息 | 上锁事务的信息 | ||
被锁的索引信息 | |||
锁的类型和模式信息 | lock_mode | lock_s---共享锁--其他事务不能加排它锁,但是可以加其他锁--防止数据被其他事务所修改 | |
lock_ls---共享意向锁--只需查询表是否上锁无需遍历数据查询 | |||
lock_x---独占锁--其他事务无法对该条数据加锁 | |||
lock_lx---独占意向锁--只需查询表是否上锁无需遍历数据查询 | |||
lock_auto_inc---自增锁--用于数据新增时主键自增值,阻塞其他插入操作,保证主键的唯一性,但是回滚操作会造成主键不连续,可以设置,增加自增值但是不加锁. | |||
特有信息 | 被锁表的信息--表锁 | lock_type | 表锁 |
表空间+页号--行锁 | 行锁 | ||
被锁行行号(bits 数组)--行锁 | rec_lock_type | 精准行锁--锁住特定的行 | |
gap锁--锁住行与行之间的间隙 防止间隙中间插入数据 |
|||
next key锁==精准行锁+gap锁 | |||
插入意向锁--特殊gap锁允许数据插入2条数据的行间隙,可以并行执行插入意向锁 |
隔离性:
脏读:a事务读取到b事务还未提交的数据
幻读:a事务2次读取同一个集合数据时,b事务对集合数据进行删除部分数据和新增了数据,a事务读到了数量不一致的行数据
不可重复度:a事务同一条数据2次读取到不同的数值,原因是b事务在a读取第二次途中修改了诗句并提交
一般常用隔离级别 serializable 看自己需求调整
//可重复读
set transaction_isolaction = 'REPEATABLE-READ'
//串行读
set transaction_isolaction = 'SERIALIZABLE'
持久性:
重做日志缓冲区 (redo log buffer)
执行器--->重做日志缓冲区 (redo log buffer)--> redo log
redo log (重做日志)可用于断电后恢复数据到磁盘中
场景:
内存数据--->----断电---x---写入磁盘
恢复市电:
redo log--->磁盘
缓冲池 (buffer pool)
执行器---->缓冲池---> 双写同步缓冲区 (doublewrite buffer)--->磁盘
内存数据-->写入磁盘中
刷盘--将存储在内存缓冲区的数据写入到磁盘中 单次16kb数据页传输 ,但是操作系统每次以4kb的大小进行数据传输,在刷盘的时候可能断电,通过建立双写同步缓冲区来解决数据页的完整性
双写同步缓冲区-里面有2份完整的页数据,断电恢复时,寻找双写同步缓冲区完整的页数据恢复,如果没有完整的页则,恢复不了