library cache
sql 执行过程
1、检查语法(检查语法,如果有错误,直接返回,省着往下执行浪费资源) seclt * form nimei;
2、检查语义(有没有这个表、当前用户有没有操作权限,如果没有直接返回)
3、hash计算(把当前的sql语句转换成oracle可以理解的hash值)
4、解析
4.1软解析(当一条sq1语句执行过,就会保存在library cache中,当再一次执行与此条sql相同的语句时,不经过cpu计算,直接调用share pool)
select * from aa ====>编译成一个XXXX的指令集
select * from aa
4.2硬解析(当软解析不成功进,经过cpu计算)
5、执行
select name from aa where id=1(先计算条件,再对比表,减少查找范围,触发索引就是先看where)
生产中share pool的命中率,应达到90%以上,这样cpu的压力就小了
触发条件:
1、标准化,书写规范(越大的公司标准化做得越好,因为人比较多,如果没有标准约束,不好干活了)
select name from emp; select name from EMP;
举例:一个大项目,肯定由多个人来完成
2、使用绑定变量
select 价格 from emp where name=1;
select 价格 from emp where name=2;
举例:互联网中,使用人比较多,每个人执行的操作不同,SQL条件也不同。
select 价格 from emp where name=:a;【绑定变量,执行SQL前给绑定变量name先赋值=1,然后再执行】
select 价格 from emp where name=:a;【绑定变量,执行SQL前给绑定变量name先赋值=2,然后再执行】
data dictionary cache
在执行sql语句时,在底层会调用 很多“数据字典”,所以设计了data dictionary cache
select * from all_users;
Optimizer收集器:
CBO优化器:衡量SQL执行计划的,选择一种最优的执行方式
例:
select name from emp where id=1;
1、全表扫描emp (cost 1000)
2、索引rowid扫描emp (cost 10)
不同的执行方式,cost的开销也是不同的,cost是通过收集器计算出来的。【周一 ~ 周五晚上,周六周日全天运行收集器】
收集器收集的是一些计算cost的条件:表有多少行?多少列?数据分布的情况?块情况?等这些值,
然后才能在不执行SQL语句的情况,才能判断SQL不同的执行情况的cost。
假设:emp表有10W行
收集器收集后,全表扫描emp表的cost的开销1000
收集器收集后,索引rowid扫描emp表的cost的开销10
CBO是做决策的吧,收集器是收集信息的吧。
举例:古代打仗(CBO:将军 Optimizer:间谍)
周一 ~ 周五晚上(每次收集全库对象,只有晚上业务空闲一些)周六周日全天运行收集器
如果白天收集,你变一行数据,收集内容就变一下,收集器压力太大了,主要是Oracle数据库的压力大了,所以都在业务低峰收集!减少压力
假设a表晚上只有10行,收集器收集了,早上的时候a表中insert了10W行,白天收集器不收集,这时候就完蛋就有问题了。
CBO判断时依据收集器,收集器收集的结果是a表只有10行。
select name from emp where id=1;
1、全表扫描emp (cost 1)
2、索引rowid扫描emp (cost 2)
所以走了全表扫描,完蛋了,a表有10W行吧,不是10行吧!Oracle不会犯这么大的错误:
操作系统块4K,Oracle块8k,扫描10行数据,全表只要扫描1个块,cost 1。先扫描索引块 cost1,通过索引块的rowid再定位数据块,cost1,一共cost2
10g以前的,优化器是RBO,基于规则的(认为索引扫描就是比全表扫描快)
有1个表是10行,存放在1个表数据块上。
如果先查索引块开销1,再查询表数据块开销1,一共开销2。
如果直接查询表数据块开销1,一共开销1。
10g开始是CBO,基于规则的cost。
假设a表晚上只有10行,收集器收集了,早上的时候a表中insert了10W行,收集器不会收集。但是表产生的变化会写到数据字典中,
如果当前一个对象,它的变化超出阀值(不管阀值是多少,Oracle自己定的)触发收集。
假设a表有100W行,第2天我Insert一条,再delete一条,对于cpu计算的结果没有影响。
假设a表有100W行,第2天我Insert了50W,它的变化超出阀值,就会告诉收集器收集一下。
举例:一个人和平时不太一样
-------------------------------------------
database buffer cache
select name from emp where name=‘zhangsan‘;
【第一次读取,然后存放在Buffer cache,第二次读取,直接从Buffer cache中取】
从内存中读取数据,肯定要比磁盘中读取快。
写操作,先写内存中,速度快,它认为内存中写完,此次操作就完了,当库空闲的时候再把内存的数据写到磁盘中dbf文件
命中率大,减少I/O压力
Buffer cache存储规则:如果用满了,从冷数据中,找与当前时间最远的优先覆盖
------------------------------------------
redo log buffer cache
先写内存中,速度快,它认为内存中写完,此次操作就完了,当库空闲的时候再把内存的数据写到磁盘的redo日志文件中
主流数据库,都是先写日志,再写数据库。日志比较重要,日志健全,数据没了,可以通过日志进行恢复
------------------------------------------
large pool 存储大数据【一次提取大的数据,存储在大池比较好,存储database Buffer cache就不好了,容易造成命中假像】
large pool存放:1、RMAN的备份数据 2、并行操作
------------------------------------------
java pool 调用前端的java指令
这5个池全在SGA(系统全局区域),在内存中分配了SGA区,在SGA又配合了以上5个池,这些池是为了加快访问速度的!!