目录
【第一课】
【第二课】
【第三课】
【第四课】接上
【第五课】
【第六课】
【第七课】
【第八课】
【第九课】
【第十课】
【补充】Oracle的数据类型
目标
1. 对Oracle11g有初步了解
2. 能熟练使用SQL语句进行增删改查
3. 熟练使用Data Generator构造性能测试基础数据
4. 能通过AWR手机Oracle性能相关
5. 能通过执行计划诊断SQL语句性能,并初步优化
6. 由Oracle出发掌握不同数据库的学习思路
目录
Oracle简介(简-体系结构)
SQL语句基础
Oracle性能测试大数据制作
Oracle 索引基础
Oracle执行计划
Oracle AWR报告详解
Oracle语句优化与课程总结
1、Oracle简介
实例(进程,内存) + 数据库(数据,配置等)= Oracle DB server
2、Oracle安装:windows上安装,镜像下载地址:
3、Oracle体系结构
1) 体系结构概述(图,手机拍照)
实例
---User process
---Server process, PGA
---Instance: SGA: Shared Pool(Library Cache, Data Dictionary Cache), Database Buffer Cache, Java Pool(不是必需的), Redo log Buffer, Large Pool(不是必需的), PMON(监控PGA), SMON(监控SGA), DBWR(针对Data),LGWQ(针对log),CKPT, Others…
数据
---Parameter file, Password file, Database(Data files, Control files, Redo Log files), Archived Log files
(1) PGA
user1 --- PGA, user2 --- PGA
每个用户都有一个与之对应的PGA;
(2) 库高速缓存区 Shared Pool (包含Library Cache, Data Dictionary Cache)
存储执行计划
执行计划类似于旅游攻略
软解析:有执行计划
硬解析:没有执行计划
显然软解析的性能会比硬解析好很多用。
(3) Database buffer cache
储存数据
用户访问的数据如果在Database buffer cache,直接返回给用户;
用户访问的数据如果不在Database buffer cache,DB从硬盘里面把数据读出来放到Database buffer cache,之后再把数据返回给客户端;
指标:缓冲命中率,越高越好(通常要求高于95%)
逻辑读:数据在Database buffer cache (从缓存读)
物理读:数据不在Database buffer cache,数据在硬盘上;
(4)Redo log Buffer日志
读日志70%+, 写30%-, 把除了读之外的其他操作都记录在Redo log Buffer里,保证数据安全。
一个进程插入数据,会同时写到redo log 和Database buffer cache里。但是提交到系统的时候,先提交日志,然后数据后提交,数据要等到满足一定的条件才能提交:8M,commit。
为什么要先提交日志?出于性能层面的考虑。
针对断电可能带来的数据丢失,可使用UPS提供不间断的供电。
2)Oracle 存储结构
-物理存储结构
基础文件:控制文件,联机重做日志文件,数据文件
外部文件:初始化文件,口令文件,归档重做日志文件
-逻辑结构
逻辑 -------- 物理
表空间 -------- 数据文件
段
区间
Oracle块 ------ 操作系统
(5)SQL 语句执行过程
a、read
1) user --- PGA ---shared pool(有执行计划) --- database buffer chache(有数据的) ---直接返回给客户端;
2) user --- PGA ---shared pool(没有执行计划) ---生成执行计划 --- database buffer chache(有数据的) ---直接返回给客户端;
3) user --- PGA ---shared pool(有执行计划) --- database buffer chache(没数据的) ---从硬盘中把数据读出来 --- 放缓存里面 ----直接返回给客户端;
4) user --- PGA ---shared pool(没有执行计划) ---生成执行计划 --- database buffer chache(没数据的) ---从硬盘中把数据读出来 --- 放缓存里面 ----直接返回给客户端;
b、write
判断数据有没有在缓存里面,如果在,直接操作,如果不在,先把数据读到缓冲中(可能是a中的某一种)
---写日志 ------先把数据写到硬盘上; (同步的数据操作)
(下面会发生的稍后一些)
---对数据进行操作 ---满足条件后才把数据写到硬盘上去;
详情参考: https://www.cnblogs.com/augus007/articles/7999586.html
(写日志是系统自身的行为,日志可用来还原,用来备份。日志远小于数据。)
(读出来的数据可能包含很多数据)
(了解上面这些有什么用?举例: 考虑性能问题,是否加索引等等)
(硬盘的底层原理:不管读多少数据,操作系统底层都是一页一页读,现在的大多数操作系统页大小都是4K)
(6)影响性能的点
库高速缓存区的大小及命中率;(空间大,能缓存的执行计划比较多)
Database buffer cache大小及命中率;
Database buffer cache和库高速缓存区数据过期算法;(80%用默认算法)
SQL语句;
索引失效和有没有索引;
DB读写数据库的性能;
数据库所在服务器自身配置有问题:CPU、men、IO;
数据库自身的软件配置;
数据库所在的操作系统(文件格式、配置(文件句柄数,防火墙是否开启))
设计对数据库性能的影响:三范式与反三范式,分库分表等;
【PPT】SQL 语句基础
1. SQL语句分类
---数据定义语言DDL D = Definition数据定义语言DDL用于建立,修改,删除数据库中的各种对象
-----表、视图、索引等如: CREATE TABLE/VIEW/INDEX
---数据操纵语言DML M = Manipulation ,用于改变数据库数据,主要有:
1) 插入:INSERT 2) 更新:UPDATE 3) 删除:DELETE 4)查询:SELETE
---数据控制语言DCL C = Query , DCL(Data Control Language)是数据库控制语言。
是用来设置或更改数据库用户或角色权限的语句,包括(grant,deny,revoke等)语句。在默认状态下,只有sysadmin,dbcreator,db_owner或db_securityadmin等人员才有权力执行;
2、基本语句—之DDL
CREATE TABLE –创建新表
ALTER TABLE –更改表数据
DROP TABLE –删除表
CREATE INDEX-创建索引
DROP INDEX –删除索引
经典面试题:
drop truncate delete的区别?
3、基本语句-DML
--插入数据
insert into table1 (id,name) values ('aa','bb');
--更新数据
update table1 set id = 'bb' where id='cc';
--删除数据
delete from table1 where id ='cc';
--查询数据
select * from table1 where id ='cc';
SELECT[ALL|DISTINCT|DISTINCTROW|TOP]
{*|talbe.*|[table.]field1[AS alias1][,[table.]field2[AS alias2][,…]]}
FROM tableexpression[,…][IN externaldatabase]
[WHERE…] [GROUP BY…] [HAVING…]
[ORDER BY…]
【执行步骤】:
先从from字句一个表或多个表创建工作表;
将where条件应用于A的工作表,保留满足条件的行;
GroupBy 将B的结果分成多个组;
Having 将条件应用于C组合的条件过滤,只保留符合要求的组;
Order By对结果进行排序;
SELECT语句中的Where条件:
大于、等于、小于或者between and;
like;
In 和exist;
其中:
Like 涉及的性能问题
In和exist涉及的性能问题
A、 in是内外表hash链接;
B、 exist是对外表做loop循环;
SELECT语句中的Where条件:
索引列出现null值,则放弃索引;
使用!=和<>操作符,会放弃使用索引;
对索引列进行运算;
解决方案是 ?
3、SQL别名
表别名或列别名
优点:使用方便,增加易读性;
取名方法:
1)、 字段后面加空格和别名;
2)、as关键字
3)、注意:当别名没有被双引号括起来,其显示结果为大写,如果别名中包含了特殊字符,或想让别名原样显示,用双引号把别名括起来。
4、order by/group by/having子句
where 语句无法聚集函数一起使用, having可以;
where 条件是作用在表上, having是作用在结果上;
select 列名 聚合函数
from 表名
{having 聚合函数 操作符 值}
group by 配合聚合函数使用,用于其他栏目某个类型的统计(分组);
聚合函数:是对一组值执行计算并返回单一的值的函数,
常与group by一起使用:
AVG;
CONUT;
MAX/MIN;
SUM;
5、常用单行函数
日期(sysdate);
字符(upper,substr、trim);
数值(round,trunc、mod);
转换(to_char、to_date、to_bumber);
通用(nvl,nvl2);
1)、nvl(expl,exp2);
2)、nvl2(expl,exp2,exp3);
6、rownum的使用
Rownum 是根据sql查询出的结果给每行分配一个逻辑编号;如何查询大于第3条的记录?
7、连接
内连接:join 和 inner join等效;需要on子句;可用where代替,且结果相同
自连接:自己和自己做连接;不需要on子句
例如:
Select worker.name,
Mgr.name
From worker,mgr
Where worker.id = mgr.id
外连接
1)左外连接
2)右外连接
3)全外连接
可省略outer,需要on子句;on 和 where性能问题 ?
【老师笔记】
(7)SQL语句基础 (重点注意有问题的SQL语句写法)
1)、SQL语句执行过程
先从from字句一个表或多个表创建工作表;
将where条件应用于A的工作表,保留满足条件的行;
GroupBy 将B的结果分成多个组;
Having 将条件应用于C组合的条件过滤,只保留符合要求的组;
Order By对结果进行排序
2)、insert语句
insert into student values('04','曾华','男',to_date('1984-9-2','yyyy-mm-dd'),'95033');
insert into student values('05','匡明','男',to_date('1988-2-4','yyyy-mm-dd'),'95031');
insert into student values('07','王丽','女',to_date('1990-3-2','yyyy-mm-dd'),'95033');
---这种类型的语句,采用批量插入可以优化,如下:
insert into student values('04','曾华','男',to_date('1984-9-2','yyyy-mm-dd'),'95033'),('05','匡明','男',to_date('1988-2-4','yyyy-mm-dd'),'95031');
---有索引、有外键等约束条件的情况下,把这些约束条件先去掉,数据插入完再加上;
3)、select 语句
select * from
---造成了过多的IO开销 ()
---造成了过多的网络开销
---甚至可能会导致索引失效 (早期版本中,解析sql语句时,看到select*时, 就默认不找索引,直接从内容里遍历,导致效率低,即索引失效。后面的版本中做了优化。 这些不只是mysql还是oracle都是通用的)
优化方法:需要使用几个字段,明确写出来(列出来)就好了
(优化后不一定有效果,影响数据库的点很多,只有当所有点都没问题,有优化时,整体结果才会有明显的优化)
in和exist (外表和内表的概念):性能低
优化方法:外表数据量大,推荐用in,反之用exist,如果两者数据量差不多的情况下,随便用;
like:有索引的情况下,like %XXX, 会导致索引失效;
优化1:
select id,name from a where like abc% --- 可能的优化方式 (基于实际的业务)
优化2:
使用函数索引的方式来解决问题;(如何使用函数索引)
null:在含有null的列上建索引,会导致索引失效,进行性能低;
优化1:
建表的时候,SQL语句指定不能为空is not null;
优化2:
建表的时候(如果是增加索引的时候,检查是否有null,有就给默认值),null给默认值;
索引列有函数、运算(!=, >=)等
优化:
尽量避免,甚至改写SQL语句;
select * from a where id -1 =5000; //表示在索引页上有运算,影响性能
--->SQL 改写
select * from a where id=5000+1;
select * from a where id=5001;
order by /group by
--问题都是性能低
优化1:用索引来优化;
优化2:调整SGA的内存参数大小;
优化3:从业务角度考虑当前的实现方式好不好;(比如开发写出来的语句,建表结构不好很烂)
作为性能测试工程师,要了解业务,了解开发如何实现业务,了解数据库,了解开发建表是否合理。
4)开发的常见问题
表设计不合理
数据库设计三范式使用不当,造成性能问题----目前可先放放,未来个人进阶
另外一种具体的表在字段选择和字段类型选择上不合理。
举例1:
create table p_test(
int id,
name char(40),
descriptrion blob
);
问题点:
可能:主键到底需要不需要?
肯定:
char ---浪费空间--- 有问题 --- 怎么优化用:varchar
blob ---浪费空间--- 有问题 --- 怎么优化用:varchar(255)
举例2:
create table p_test(
int id,
createTime varchar(40),
fromIpAddress varchar(20)
);
问题点:createTime、fromIpAddress可用用简单数据类型来搞定;
总结:字段能用简单的就用简单的类型,字段长度能小就尽可能小;
https://www.cnblogs.com/buxingzhelyd/p/8984173.html (Oracle的数据类型,重要!)
5)、表之间的各种连接关系
真实世界:1:n,n:1等关系 ---开发抽象实现的
SQL层面:各种连接(内连接、外连接等);----对真实世界中各关系的实现
DB内部实现:各种算法(迭代循环、归并排序、哈希连接)---我们测试干预不了的,我们能做的事情是,SQL改写或者调整等来影响DB内部的实现。
(到底能不能做,一定要基于业务)
(数据设计不合理,就需要分表,表多了也不优。一旦连接的表到了4张之后,或者一个表加了6个以上的索引的时候,就需要考虑表和数据的设计是不是合理的了)
1、缓存读写策略
当前缓存使用主流有两种策略:
1)、旁路策略
2)、写穿、写穿策略
https://www.cnblogs.com/llzhang123/p/9037346.html
2、数据制作方法
1)、为什么要制作数据: 为了更加真实的模拟现实情况。模拟真实的用户环境,尤其涉及SQL中DDM操作时。
2)、都有哪些方法:
用代码生成: API代码(本质是有界面或没界面的客户端),SQL代码(存储过程)
用工具生成: UI自动化工具生成数据,性能测试工具生成(Data Generator);
第三方库导入:生产数据脱敏后直接用(让运维导数据时注意提醒脱敏)
推荐:采用性能测试工具来生成。
3)、如何知道我们要制作多少数据:
根据性能测试需求分析出来的结果决定我们要生成多少数据。(根据系统的具体情况来定)
原则:宁多勿少(但是如果多过份了,也是我们不能接受的)
4)、业界数据制作发展到了那几个阶段(了解)
业界目前发展经过了三代
第一代:直接代用上述方法生成测试数据;
第二代:对上述代码做了封装,将其做到了平台化;
第三代:平台化后的数据生成支持跨平台,支持自动化;
5)、性能测试到底需要制作什么数据
基础数据(比如登陆用的用户名、密码)、业务数据(订单号、支付信息)
铺垫数据(比如测登陆时提前准备一些用户名账号):
消耗数据(每测一次就消耗掉一个数据,订单号,支付数据之类的):
性能测试是对多个接口做测试.接口测试就是单个接口测试.
很多性能测试问题没测出来的原因:环境和线上真实的环境有差异,数据量不够.
6)、数据制作
先生成所需要的表
create table datatest(
deptno number(6),
dname varchar2(20),
loc varchar2(20)
);
根据业务需要选择合适的数据生成规则,生成数据。
客户端: PL SQL developer -> 工具-> 数据生成器
建表建数据过程:
SQL建表语句,运行,生成表。
针对每个表字段,选择相应的生成数据的规则(变量,范围, 函数等)。
左下角三个按钮,先预览生成的数据,再运行最后一个按钮将这些数据插入表格。
查询表格,看看是否已成功插入数据。
PS:
数据制作的难点:在于分析表和表之间的关联关系(和开发聊、自己看代码、慢慢猜);
如果需要生成的数据比较多,那就分批插入就好了。
课堂练习
create table stu33(
sid number(10), //持续递增,Sequence(1,1),第一个参数表示从1开始,第二个参数表示间隔
sname varchar(30) , //随便组合一下,比如就用FirstName
ssex varchar(20) , //man或women, 用枚举, List(‘men’,’women’,)
sbirthday DATE, //to_date(‘2003/07/11’,‘yyyy/mm/dd’)会生成乱码 . 试试用随机数Random(‘1980/01/01’, ‘2000/12/21’)
stel number(11), //第一位固定为1, List(‘1’,)+[0(10..10)]
sclass varchar(20) //List(‘1年级’, ‘2年级’,)
);使用Data Generator生成1000条数据 //在Number of record: 10000..10000
补充:不同表格中字段有关联的时候怎么处理?用这种生成数据的工具不好处理,用存储过程来处理。
上节课练习讲解:
1)日期出不来怎么办?方法不限,能拼成想要的数据就行。
2) 有的项的值是空的,是因为比如List(‘1年级’, ‘2年级’,)最后多了一个逗号, 把逗号去掉就行
3)数据量很大的时候,要分批插入。可以通过Optionsl里控制一下节奏,有两个可以设置:延迟,每个多少时间提交一次。
4)插入之后要关注是否插入成功。不成功的原因和处理方式:先看有没有权限?确保有权限。然后看SQL是否成功,可以单独执行SQL语句看看。
3、索引基础
1)、什么是索引?
为了提高查询效率的一种数据结构(可以是一棵树,也可以是一张表), 类似于字典。
2)、索引的原理?
没有索引数据的查找是,全表扫描;
有了索引之后,数据查找时,先在索引中查找,如果索引中能找到,通过索引给出的线索到数据库中查询所需的数据;
如果索引里面也没找到,那就进行全表扫描(通常是索引失效引起的)
3)、索引分类
--B树索引:从数据结构的角度来说的(唯一索引/主键索引 ===>非唯一索引),可以是单列索引,也可以是复合索引;
--位图索引:从数据结构的角度来说的
--单列索引和复合索引:从索引所包含的列来说的
适用场景:
B树索引使用列基础非常大,且离散度的字段建立索引;(列基数大指的是在这一列上拥有的数据量大,而且不重复)
位图索引适用于列基础小,且离散度不高的字段建立索引;(列基数上重复性很高,比如男和女,就是离散度不高的字段)
比如:四川7000W要建立索引,使用B+树这种;
而如果是在四川7000W人的性别字段上建立索引,位图索引会比较适合。
alter table table_name add index index_name(id); ---(B+数的)单列索引
alter table table_name add index index_name(id1,id2); ---(B+数的)复合索引
4)、索引使用原则
--对表而言,是不是大表,小表没有必要建立索引,大表才考虑建立索引;---大表小表都是相对的,没有绝对的标准,也不能单纯从数据量的情况来看,一切以性能测试结果说明为准;
--建立索引的索引的时候,要在常用的字段上建立索引;
--B树索引使用列基础非常大,且离散度的字段建立索引;
--位图索引适用于列基础小,且离散度不高的字段建立索引;
--索引在建立过程中,要适当考虑索引失效的情况;
PS:如果你的表你建立索引在> 4个,这个要你要考虑一下的表设计是不是合理的;因为过多的索引反而会影响到你的查询速度。
key 和索引有关系也有区别。
PS:不是有了索引之后,数据库查询的时候,就一定会走索引。结构会有自己的算法,计算之后会选择最优的方法去搜索。
不管用什么方式,一定要有铺垫数据。
5)、索引的底层算法 (很重要,很多公司的面试题)
a、为什么采用B+树作为索引结构;
线性查找 --- 查找效率不高
二分查找 --- 随着数据量的增大,复杂度还是很大(并且隐含的排序这个操作的开销会很大)
二叉树查找 -- 极端情况,二叉树会变成线性表,随着数据量的增大,复杂度还是很大
红黑树 --- 极端情况下,树的高度还是很高,树的高度越高,IO开销越大;(红黑树动画在线演示PS :https://rbtree.phpisfuture.com/)
B树--- 通过引入度(一个节点可以存储多少数据,我们称为度:4k)
B+树---mysql只有B+树,oracle有多种。
b、为什么采用位图作为索引结构
因为在某些字段离散度不高的情况,如果采用B+树这种数据结构,效率不高。
6)、如何利用索引优化性能问题
首先是要值得优化;
需要采用索引来进行优化;
采用索引来优化;
对数据库而已,我们的要求是:能不做就不做,能少做就少做。
不管有多大的数据,都是需要铺垫数据的。铺垫数据多少,要看系统要使用多长时间?这个时间后要如果进行归档,数据都被清掉,一切又从零开始。铺垫数据可以是消耗数据,也可以是不消耗的数据。铺垫数据的目的在于让我们系统查询起来时跟真实情况一样。
补【PPT】
4、创建/删除索引
CREATE [UNIQUE] | [BITMAP] INDEX index_name --unique表示唯一索引
ON table_name([column1 [ASC|DESC],column2 --bitmap,创建位图索引
[ASC|DESC],…] | [express])
[TABLESPACE tablespace_name]
drop index index_name –删除索引
5、索引失效示例
典型:
通配符在搜索词首出现时,oracle不能使用索引;
不要在索引列上使用not,可以采用<、>代替;
索引上使用空值比较将停止使用索引;
例如:
--name上创建索引;
create index index_name on student(‘sname');
--下面的方式oracle不适用name索引
select * from student where name like '%wish%';
--如果通配符出现在字符串的其他位置时,优化器能够利用索引;如下:
select * from student where name like 'wish%';
6. 索引使用总结
(1)小表:不建立索引
(2)大表:查询时走了全表扫描
---没有索引,则建立索引:
列基数大建立B树索引
列基数小建立位图索引
经常查询的列简历索引,且放到最前面
---检查索引失效:
唯一索引引起非唯一索引失效
组合索引中,第一列的值没有被使用到
索引简历的列中包含null值
like参与的模糊查询中,出现了 like %XXX%的情况, 可改成instr(字段名, ‘XXX’)
索引列上进行了数学运算
索引列上使用了Not, 可以采用<,>代替
索引列上使用了函数
(3)索引使用过程中的一些误区
索引并不是越多越好
并不是有了索引查询速度就一定快
并不是有了索引就能完美解决数据库性能问题
1、执行计划
执行计划并不是真实的在执行SQL语句,而是在模拟SQL语句执行;
(SQL语句执行时,Oracle根据自身算法计算出来的执行路径,类似于我们自驾去西藏时做的自助游攻略)
所以:执行计划中看到的各种开销只有参考意义,没有决定意义。
执行计划的意义:SQL优化(调优)的第一步。
使用执行计划的前提:一定的数据量和硬件环境。
执行计划要看的点:
1)cost值大小 --- 一般越小越好;
2)SQL语句的执行顺序:向右缩进最多的优先执行,向右缩进相同的从上往下执行;
---缩进最多的最先执行(缩进相同时,最上面的最先执行)
---同一级如果某个动作没有子ID,就最先执行
---同一级的动作执行时,遵循最上最右先执行的原则
看懂执行计划(嵌套循环连接,排序合并连接,哈希连接, 图略,手机拍照)
3)表的访问方式:
Index UNIUQE SCAN:索引唯一扫描
Index Range Scan:索引范围扫描;
Index full scan : 索引全扫描(覆盖索引的情况下)
Index fast full scan:索引快速扫描
Index skip scan:索引跳跃扫描(复合索引第一列没有出现在查询条件中,oracle有mysql无)
4)表的连接方式:
迭代循环:
归并排序:
哈希连接:
PS:
在做对比测试中,除了保证数据量相同,硬件环境相同外,还要清掉库高速缓存区和database buffer cache。 屏蔽这两个点的影响:
如何清除命令:
alter system flush shared_pool;
alter system flush buffer_cache;
5)PL/SQL执行计划进行SQL调优步骤
---查看cost, 获得总体印象
---分析执行步骤
---分析表的访问方式
---分析表连接方式和连接顺序
---项目组求助
6)使用执行计划优化SQL语句
例1:
create table datatest2
( deptno NUMBER(6),
dname VARCHAR2(20),
loc VARCHAR2(20));
使用 Data Generator生成20000条数据。
在执行计划中输入:
select * from datatest2 where deptno =15000 ;观察执行计划,重点cost值;
创建索引
create index dindex on datatest2(deptno)
在执行计划中输入:
select * from datatest2 where deptno =15000 ;观察执行计划,重点cost值;
在执行计划中输入:
select * from datatest2 where dname like ‘%a%’ ; 观察执行计划,重点cost值;
在执行计划中输入:
select * from datatest2 where dname like ‘a%’ ; 观察执行计划,重点cost值;
7)关于执行计划
(1)、执行计划,只是SQL运行前可能的执行方式,实际运行时可能因为软硬件环境的不同,有所改变,而且cost高的执行计划,不一定在实际运行起来,速度就一定差。
(2)、对于表的连接顺序,多数情况下使用的是嵌套循环,尤其是在索引可用性好的情况下,使用嵌套循环式最好的;当ORACLE发现需要访问的数据表较大,索引的成本较高或者没有合适的索引可用时,会考虑使用哈希连接,以提高效率。排序合并连接的性能最差,但在存在排序需求,或者存在非等值连接无法使用哈希连接的情况下,排序合并的效率,也可能比哈希连接或嵌套循环要好
(自己总结)
写SQL语句,选择,右键,Explian Plan,弹出一个框,就是执行计划内容(Tree, HTML,Test, XML)。
SQL语句执行计划的多个注意点:
1)向右缩进越多的先执行。缩进情况相同的,从上往下执行。
2)注意看各个列的意思(Description, owner, object name, cost, cardinality, bytes…):
--cost越小说明执行计划越好,cost的单位是单位块,大小是相对意义的,只是优化的一个参考值而已(在一定的数据量,一定的硬件环境中)。执行计划得出的cost只是一个估算值。执行计划只是利用系统中的各种数值和算法得出。cost计算时,很多PC的事情开销,是没算进来的, 在数据库之外。
--对数据库来说,什么是执行计划:
硬盘 à 内存 à PC à 人:人给指令给PC, PC要求内存加工数据,数据是从硬盘读取的,内存加工完数据后返回给PC。 这个过程中,硬盘到PC之间的这段操作,就是执行计划。
操作:
在PLSQL中生成数据,插入数据。
然后SQL语句(select * from datatest)右键执行计划,看cost值。
cost值不太好,这里有两个坑:
1)加了索引也不一定好,因为不一定有索引就一定要用索引,索引不一定是最快的。
2)要把告诉缓存区和database buffer cache的数据清掉。
有没有改善的空间?
--在表中加个索引,
alter table datatest add index idx_id(DEPTNO)
create index idx_id on datatest(DEPTNO)
然后再执行上面相同的SQL语句(select * from datatest),看执行计划的结果。此时看到还是全表扫描,为啥不走索引?因为索引加在deptno字段,没使用到。
改SQL语句: select deptno from datatest where deptno=1000;
此时看执行计划,就是走了索引,cost值小了,即得到优化。
然后再试试去掉索引:
drop index idx_id;
再执行计划,看cost: 又变成2(没有得到优化).
然后再清掉:
alter system flush shared_pool;
alter system flush buffer_cache;
再执行计划,看cost: 还是2(没有得到优化).
然后再加索引
再清掉shared_pool,buffer_cache
再执行计划,看cost: 2(得到优化).
补充:
SQL语句中的大于小于会导致索引失效。如果SQL里没有大于小于但还是走全表扫描,不走索引,是因为执行计划自己评估下来后得出走全表扫描比较好。
小结:
怎样利用执行计划来对SQL语句进行优化。先看cost, 然后修改SQL(加索引啊,清缓存啊…),然后执行计划,再看cost是否有优化。有的话说明改好了一些,没有的话,继续改。
1. Oracle AWR 报告详解(PPT),本质就是一个监控
先要生成AWR报告,用PLsql无法生成。用别的(doc命令)。
1)简介
AWR (Automatic Workload Repository) 是自动负载信息库的英文缩写,AWR报告是Oracle 10g以后版本提供的一种性能收集和分析工具,是Oracle数据库的一个体检报告。
通过它可以对数据库运行状态进行监控,发现数据库使用过程中可能存在的性能瓶颈。
2)SQL语句执行过程
3)生成AWR报告
Dos 下输入:
1、sqlplus system/oracle as sysdba;
2、SQL> @?/rdbms/admin/awrrpt.sql;
3、输入 report_type 的值: html 报告格式,还可以是text;
4、输入 num_days 的值: 3 假设是3天;
5、输入 begin_snap 的值: 192 假设是192
6、输入End Snapshot Id specified: 194 假设是194
7、输入 report_name 的值: 20171225_awr.html 报告的名字,可自定义;
8、输入exit
9、到指定路径(首次打开dos窗口的路径),找到报告并打开;
4)AWR报告中的关键指标
---平台信息: 主机信息,内存信息,主机系统
---Oracle版本信息
---ElapsedTime/DB time/Average Active Session
---Logical Read / Logical Write & Physical Read/Physical Write
---Parse: soft Parse > 95%, hard Parse
---Instance Efficiency Percentages: Buffer Hit> 95%, Latch Hit > 95%,
Buffer Hit低的原因:Buffer设置小,没有绑定变量,SQL语句有问题
---SQL Statistics:
SQL ordered by Elapsed Time (关注高频耗时)
SQL ordered by CPU Time (关注高频耗时)
Complete List of SQL Text
(2)如何看报告? 先看整体再看详细。
关注: DB时间,软硬解析命中率,高速缓存/buffer cache命中率,逻辑数越大越好,物理数越小越好,
1)DB time不包括Oracle后台进程消耗的时间。如果DB time远小于Elapsed时间(和数据库相关的总的时间),说明数据库比较空闲。 db time = cpu time + wait time(不包括空闲等待)(非后台进程)。
说白了DB time就是记录的服务器花在数据库运算(非后台进程)和等待(非空闲等待)上的时间。
DB time = cpu time + all of nonidle wait event time
在79分钟(Elapsed)里(其间收集了3次快照数据),数据库耗时11分钟(DB time),RDA数据中显示系统有8个逻辑cpu(4个物理CPU),平均每个CPU耗时1.4分钟,CPU利用率只有大约2%(1.4/79). 说明系统压力很小。
即:要考虑DB time和核数的关系。
2)物理读和物理写(有对应的单位):
物理读越小越好,逻辑读是越大越好。
3)硬解析和软解析:
不知道一个硬解析的值好还是不好,接下来看buffer cache命中率还行,锁的命中率还行,但是软解析命中率不太好,分析一下什么原因。
4)往下拉,看报告主体。
SQL语句的状态 (消耗比较多的SQL语句。。。)
IO的状态
Buffer cache的细节信息
关注哪些点再强调一些:高频(Executions) 耗时(Elapsed time)
SQL id (如果数据库被攻击,这一列会看到五花八门的ID?IP?)
SQL Module (连接的一些外部的客户端?)
SQL Text (SQL语句的描述)
怀疑某条SQL语句有问题,如何处理?
把该SQL语句放到PL SQL 中,看执行计划,开销,然后修修补补
实例:https://www.cnblogs.com/bingjava/p/5255760.html (具体看看,学习。真实案例!)
快照可以手动生成。
2. SQL语句优化原则
---不要让Oracle做得太多
避免使用*
exists和in关系(内表数据量大时用exists, 反之用in)
---合理使用索引
---减少访问次数
3. 本课程内容总结
(1)数据生成: Data Generator
(2)执行测试: 性能测试工具(UI/数据库测试工具)
(3)问题SQL:AWR找到有问题的SQL语句
(4)优化SQL: 执行计划优化SQL语句
4. 关于SQL性能优化
---依据: SQL的执行计划,性能报告
---方法:充分利用索引,尽量减少I/0, 尽量的缩小数据(业务上支持)
---如何判断:并不是性能越高越好,是在合理的成本下,满足业务应用就好。脱离业务需求谈技术都在耍流氓。性能测试中,被测系统是个整体,除了SQL语句,我们还可以从如下方面发力:
业务优化: 最显著,成本太高
程序优化: 收益高,时间长
资源优化: 省事不省心,缓解
配置优化: 提高利用率,最简单
推荐书籍: 《高性能MySQL》第三版
学习方法:
学技术,多动手多总结
记不住的原因:用的少,没有体系化
自学能力,自律。真正牛逼的技术,更多的是自己琢磨出来的。
要有替换性想法,任何人任何书,全听不行,全不听也不行。
能解决问题的就可以,其他的当做理论。
常用的数据库字段类型如下:
字段类型 中文说明 限制条件 其它说明
CHAR 固定长度字符串 最大长度2000 bytes
VARCHAR2 可变长度的字符串 最大长度4000 bytes 可做索引的最大长度749
NCHAR 根据字符集而定的固定长度字符串 最大长度2000 bytes
NVARCHAR2 根据字符集而定的可变长度字符串 最大长度4000 bytes
DATE 日期(日-月-年) DD-MM-YY(HH-MI-SS) 经过严格测试,无千虫问题
LONG 超长字符串 最大长度2G(231-1) 足够存储大部头著作
RAW 固定长度的二进制数据 最大长度2000 bytes 可存放多媒体图象声音等
LONG RAW 可变长度的二进制数据 最大长度2G 同上
BLOB 二进制数据 最大长度4G
CLOB 字符数据 最大长度4G
NCLOB 根据字符集而定的字符数据 最大长度4G
BFILE 存放在数据库外的二进制数据 最大长度4G
ROWID 数据表中记录的唯一行号 10 bytes ********.****.****格式,*为0或1
NROWID 二进制数据表中记录的唯一行号 最大长度4000 bytes
NUMBER(P,S) 数字类型 P为总位数,S为小数位数
DECIMAL(P,S) 数字类型 P为总位数,S为小数位数
INTEGER 整数类型 小的整数
FLOAT 浮点数类型 NUMBER(38),双精度
REAL 实数类型 NUMBER(63),精度更高
数据类型 参数 描述
char(n)
n=1 to 2000字节 定长字符串,n字节长,如果不指定长度,缺省为1个字节长(一个汉字为2字节)
varchar2(n)
n=1 to 4000字节 可变长的字符串,具体定义时指明最大长度n,这种数据类型可以放数字、字母以及ASCII码字符集(或者EBCDIC等数据库系统接受的字符集标准)中的所有符号。
如果数据长度没有达到最大值n,Oracle 8i会根据数据大小自动调节字段长度,如果你的数据前后有空格,Oracle 8i会自动将其删去。VARCHAR2是最常用的数据类型。可做索引的最大长度3209。
number(m,n)
m=1 to 38
n=-84 to 127 可变长的数值列,允许0、正值及负值,m是所有有效数字的位数,n是小数点以后的位数。
如:number(5,2),则这个字段的最大值是99,999,如果数值超出了位数限制就会被截取多余的位数。
如:number(5,2),但在一行数据中的这个字段输入575.316,则真正保存到字段中的数值是575.32。
如:number(3,0),输入575.316,真正保存的数据是575。
date
无 从公元前4712年1月1日到公元4712年12月31日的所有合法日期,Oracle 8i其实在内部是按7个字节来保存日期数据,在定义中还包括小时、分、秒。
缺省格式为DD-MON-YY,如07-11月-00 表示2000年11月7日。
long
无 可变长字符列,最大长度限制是2GB,用于不需要作字符串搜索的长串数据,如果要进行字符搜索就要用varchar2类型。long是一种较老的数据类型,将来会逐渐被BLOB、CLOB、NCLOB等大的对象数据类型所取代。
raw(n)
n=1 to 2000 可变长二进制数据,在具体定义字段的时候必须指明最大长度n,Oracle 8i用这种格式来保存较小的图形文件或带格式的文本文件,如Miceosoft Word文档。
raw是一种较老的数据类型,将来会逐渐被BLOB、CLOB、NCLOB等大的对象数据类型所取代。
long raw
无 可变长二进制数据,最大长度是2GB。Oracle 8i用这种格式来保存较大的图形文件或带格式的文本文件,如Miceosoft Word文档,以及音频、视频等非文本文件。
在同一张表中不能同时有long类型和long raw类型,long raw也是一种较老的数据类型,将来会逐渐被BLOB、CLOB、NCLOB等大的对象数据类型所取代。
blob /clob /nclob
无 三种大型对象(LOB),用来保存较大的图形文件或带格式的文本文件,如Miceosoft Word文档,以及音频、视频等非文本文件,最大长度是4GB。
LOB有几种类型,取决于你使用的字节的类型,Oracle 8i实实在在地将这些数据存储在数据库内部保存。
可以执行读取、存储、写入等特殊操作。
bfile
无 在数据库外部保存的大型二进制对象文件,最大长度是4GB。
这种外部的LOB类型,通过数据库记录变化情况,但是数据的具体保存是在数据库外部进行的。
Oracle 8i可以读取、查询BFILE,但是不能写入。
大小由操作系统决定。