SQL优化入门(视频笔记20210720)

目录

【第一课】

【第二课】

【第三课】

【第四课】接上

【第五课】

【第六课】

【第七课】

【第八课】

【第九课】

【第十课】

【补充】Oracle的数据类型


【第一课】

目标

1. 对Oracle11g有初步了解

2. 能熟练使用SQL语句进行增删改查

3. 熟练使用Data Generator构造性能测试基础数据

4. 能通过AWR手机Oracle性能相关

5. 能通过执行计划诊断SQL语句性能,并初步优化

6. 由Oracle出发掌握不同数据库的学习思路

目录

Oracle简介(简-体系结构)

SQL语句基础

Oracle性能测试大数据制作

Oracle 索引基础

Oracle执行计划

Oracle AWR报告详解

Oracle语句优化与课程总结

1Oracle简介

实例(进程,内存) + 数据库(数据,配置等)= Oracle DB server

2Oracle安装:windows上安装,镜像下载地址:

3Oracle体系结构

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,数据在硬盘上;

4Redo log Buffer日志

         读日志70%+, 写30%-, 把除了读之外的其他操作都记录在Redo log Buffer里,保证数据安全。

一个进程插入数据,会同时写到redo log 和Database buffer cache里。但是提交到系统的时候,先提交日志,然后数据后提交,数据要等到满足一定的条件才能提交:8M,commit。

为什么要先提交日志?出于性能层面的考虑。

针对断电可能带来的数据丢失,可使用UPS提供不间断的供电。

2Oracle 存储结构

-物理存储结构

基础文件:控制文件,联机重做日志文件,数据文件

外部文件:初始化文件,口令文件,归档重做日志文件

-逻辑结构

   逻辑  --------  物理

表空间 -------- 数据文件

区间

Oracle块 ------ 操作系统

【第二课】

(5)SQL 语句执行过程

aread

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(没数据的) ---从硬盘中把数据读出来 --- 放缓存里面 ----直接返回给客户端;

  

bwrite

判断数据有没有在缓存里面,如果在,直接操作,如果不在,先把数据读到缓冲中(可能是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性能问题 ?

【老师笔记】

7SQL语句基础 (重点注意有问题的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都是通用的)

优化方法:需要使用几个字段,明确写出来(列出来)就好了

(优化后不一定有效果,影响数据库的点很多,只有当所有点都没问题,有优化时,整体结果才会有明显的优化)

        

【第四课】接上

inexist  (外表和内表的概念):性能低

优化方法:外表数据量大,推荐用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.htmlOracle的数据类型,重要!

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数据库的一个体检报告。

通过它可以对数据库运行状态进行监控,发现数据库使用过程中可能存在的性能瓶颈。

2SQL语句执行过程

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窗口的路径),找到报告并打开;

4AWR报告中的关键指标

---平台信息: 主机信息,内存信息,主机系统

---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》第三版

学习方法:

学技术,多动手多总结

记不住的原因:用的少,没有体系化

自学能力,自律。真正牛逼的技术,更多的是自己琢磨出来的。

要有替换性想法,任何人任何书,全听不行,全不听也不行。

能解决问题的就可以,其他的当做理论。

【补充】Oracle的数据类型


常用的数据库字段类型如下:


字段类型    中文说明  限制条件    其它说明
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,但是不能写入。
大小由操作系统决定。

上一篇:java-如何将测试功能应用于遗传算法


下一篇:C# EF优化