1.oracle优化器种类

 自从ORACLE 10g以来,oracle就存在了两种优化器--CBO和RBO。

    RBO: Rule-Based Optimization 基于规则的优化器

     CBO: Cost-Based Optimization 基于代价的优化器

 RBO顾名思义,oracle在系统内部定义了一系列sql语句执行了规则,sql严格按照规则来生成执行计划,并执行,对表的数据分布和变化不敏感,所以才有了CBO的出现。

 CBO是对每个查询所耗费的资源进行量化,从而可以根据这个量化的值选出最佳的执行计划,一个查询所耗费的资源可分为:I/O,CPU,network三部分代价。

 <1>I/O一般是将数据库文件中的数据库块读入内存(磁盘读入内存)所耗费的资源

 <2>CPU代价是内存中处理数据的代价,在这些数据上进行排序sort,表的join连接操作,这都需要cpu资源的耗费。

 <3>network是远程查询数据库表或者执行分布式连接的网络传输代价

注:oracle中数据库的概念是oracle数据文件中的最小单位,由多个操作系统块组成。

 数据库使用的优化器根据参数optimizer_mode决定,取值如下:

  • RULE 使用RBO优化器

  • choose 数据字典有被引用的对象的统计数据,则使用CBO,否则使用RBO

  • all_rows 以数据吞吐量为主要目标,以便使用最少的资源完成语句

  • first_rows 以数据响应时间为主要目标,以便快速查询开始的n行数据

  • first_rows[1|100|1000|n] 让优化器选一个能把响应时间减到最小的执行计划,以迅速产生查询结果的前n行


2.执行计划中的概念

  • row_sources(行源) 根据where中条件限制后的结果集或者多表链接后的结果集,不单指table

  • predicate(谓词)

  •  access谓词 这个谓词的条件的值将会影响数据的访问路径(一般针对索引)

  •  fileter谓词 起过滤作用 

  • driving table(驱动表,外表,outer table) 用于嵌套连接和哈希连接

  • probed table(被探查表,内表,inner table)

  • access path(访问路径)

  •  full table scans(全表扫描) oracle顺序读取分配给表的每个数据块,知道表的最高水位线。可以一次性读取多个块,block的数量则由操作系统的I/O最大值和multiblock(db_block_multiblock_read_count)参数共同决定

  •    Table Access by ROWID(通过ROWID的表存取/rowid lookup)

  •    Index Scan(索引扫描/index lookup)

    ......

  • sort-mergejoin(排序合并连接)

  • nested loop(嵌套连接)

  • hash join(哈希连接)


3.sql语句执行过程

 每种类型sql语句都要一下n个阶段:

 <1>create a cursor

 <2>parse the statement解析语句 

   判断语法是否正确,权限是否充足,查找数据字典是否符合表,列的定义,锁分析,生成执行计划等,这一步骤比较耗费资源,一般都应该减少解析次数。但是也有下述这种情况:当sql的基表发生的dml语句导致数据分布发生了较大的变化(可能影响的执行计划),如果还采用之前的执行计划,有可能性能会不太好,这时候最好重新进行表分析,重新生成执行计划,所以这个还是要看具体情况决定。

 <5>bind any variables

 <7>run the statement

 <9>close the cursor

若使用了并行功能

<6>parallelize the statement 并行执行语句

若是select语句

<3>describe result of a query 描述查询结果集

<4>define output of a query 定义查询输出

<8>fetch rows of a query 获取查询行


4.sql中标的连接方式

 排序合并连接

 

  1. row_source1按照连接列进行排序,row_source2按照连接列进行排序

  2. row_source1,row_source2一起执行合并操作,即将两个row_source按照连接条件连接起来


 嵌套循环

一般原则是选择驱动表是较小的row_source

优点:可以快速返回已经连接的行,不必等所有行连接操作处理完才返回数据,可实时响应


 hash连接

较小的row_source用来构建hash table的bitmap,第二个row_source被用来hansed,并与第一个row_source生成的hash table匹配,以便进一步连接,比bitmap用来check hash table中是否有匹配的行。


三种连接方式比较:

smj:第一,对于非等值连接效率较高。关联列上有索引更好。对于两个较大的row_source比nl效率高

nl:第一快速响应。外部表较小,内部表上有唯一索引/高效的非唯一索引

hj:hash_area_size参数要合适。只能用于等值连接。


5.hints

 /*+ ordered*/:form子句从左到右顺序连接

 /*+ full(table)*/:全表扫描

 /*+ index_ffs(table [index_name])*/:快速全表扫描

 /*+ no_index(table [index])*/不使用索引

 /*+ use_nl(table[,table...])*/ 嵌套循环

  例:use_nl(a c)此时a是内部表,c是驱动表

此外有外关联的表不能作为驱动表。若外关联与ordered指定的顺序有冲突,则忽略ordered hint


6.trace的使用


SELECT ss.SID,
       ss.SERIAL#,  --1.sid和serial#共同表示唯一一个session
       ss.USERNAME, --2.数据库用户名
       ss.MACHINE,  --3.连接数据库所在程序的机器名,如下图
       ss.PROGRAM, --连接数据库的程序名
       p.SPID as serverid,--与程序对应的server段的服务器进程号,在unix中较有用
       ss.SERVER,    --程序连接数据库模式:DEDICATED专用模式(trace只适用该模式)。shared
                     --共享模式
       ss.LOGON_TIME --连接数据库的登录时间
  FROM v$session ss, v$process p
 WHERE p.ADDR = ss.PADDR
   AND ss.USERNAME = 'SYS';

3 -->oracle sql优化总结_第1张图片


使用trace过程:

  1. 识别要跟踪的client程序到数据库的连接,上述sql可查

  2. 设定相应的parameter

    time_statistics 收集trace信息时,是否收集时间信息,可以知道一个sql各阶段耗时情况

    user_dump_dest 存放跟踪的文件位置

    max_dump_file_size 配置跟踪文件的最大值

  使用procedure设置参数

exec dbms_system.set_bool_param_in_session(sid => '65',
                      seria# => '55',
                      parnam => 'time_statistics',
                      bval => true);

wKiom1jH9oiTqjoqAABj0Uisk7U429.png-wh_50

exec dbms_system.set_int_param_in_session(sid => '65',
                     seria# => '55',
                     parnam => 'user_dump_dest',
                     intval => true)


3.启用跟踪功能

exec dbms_system.set_sql_trace_in_session(8,3,true);


4.run一段时间


5.关闭trace

exec dbms_system.set_sql_trace_in_session(8,3,false);


6.格式化文件

tkprof xxx.trc xx.out sys=no explain=scott/tiger

TKPROF  filename1, filename2 [ SORT  = [ opion][,option] ]
  [  PRINT = integer ]
  [ AGGREGATE  = [ YES | NO ] ]
  [ INSERT = filename3 ]
  [ SYS = [ YES | NO ]  ]
  [  [ TABLE = schema.table ] | [ EXPLAIN = user/password ]  ]
  [  RECORD = filename ]

参数解析

SORT     在输出到输出文件前,先进程排序。如果省去,则按照实际使用的顺序输出到文件中。排序选项有以下多种:
  prscnt  number of times parse was called
  prscpu  cpu time parsing
  prsela  elapsed time parsing
  prsdsk  number of disk reads during parse
  prsqry  number of buffers for consistent read during parse
  prscu   number of buffers for current read during parse
  prsmis  number of misses in library cache during parse
  execnt  number of execute was called
  execpu  cpu time spent executing
  exeela  elapsed time executing
  exedsk  number of disk reads during execute
  exeqry  number of buffers for consistent read during execute
  execu   number of buffers for current read during execute
  exerow  number of rows processed during execute
  exemis  number of library cache misses during execute
  fchcnt  number of times fetch was called
  fchcpu  cpu time spent fetching
  fchela  elapsed time fetching
  fchdsk  number of disk reads during fetch
  fchqry  number of buffers for consistent read during fetch
  fchcu   number of buffers for current read during fetch
  fchrow  number of rows fetched
  userid  userid of user that parsed the cursor
PRINT        只列出输出文件的第一个integer 的SQL语句。默认为所有的SQL语句。
AGGREGATE    如果= NO ,则不对多个相同的SQL进行汇总。
INSERT       SQL 语句的一种,用于将跟踪文件的统计信息存储到数据库中。在TKPROF创建脚本后,在将结果输入到数据库中。
SYS         禁止或启用 将SYS用户所发布的SQL语句列表到输出文件中。
TABLE       在输出到输出文件前,用于存放临时表的用户名和表名。
EXPLAIN     对每条SQL 语句确定其执行规划。并将执行规划写到输出文件中。
   其中比较有用的一个排序选项是fchela,即按照elapsed time fetching来对分析的结果排序
(记住要设置初始化参数timed_statistics=true),生成的文件将把最消耗时间的sql放在最前面显示。
另外一个有用的参数就是sys,这个参数设置为no可以阻止所有以sys用户执行的sql被显示出来,
这样可以减少分析出来的文件的复杂度,便于查看。
首先解释输出文件中列的含义:
CALL:每次SQL语句的处理都分成三个部分
Parse:这步将SQL语句转换成执行计划,包括检查是否有正确的授权和所需要用到的表、列以及其他引用到的对象是否存在。
Execute:这步是真正的由Oracle来执行语句。对于insert、update、delete操作,这步会修改数据,对于select操作,这步就只是确定选择的记录。
Fetch:返回查询语句中所获得的记录,这步只有select语句会被执行。
COUNT:这个语句被parse、execute、fetch的次数。
CPU:这个语句对于所有的parse、execute、fetch所消耗的cpu的时间,以秒为单位。
ELAPSED:这个语句所有消耗在parse、execute、fetch的总的时间。
DISK:从磁盘上的数据文件中物理读取的块的数量。一般来说更想知道的是正在从缓存中读取的数据而不是从磁盘上读取的数据。
QUERY:在一致性读模式下,所有parse、execute、fetch所获得的buffer的数量。一致性模式的buffer是用于给一个长时间运行的事务提供一个一致性读的快照,缓存实际上在头部存储了状态。
CURRENT:在current模式下所获得的buffer的数量。一般在current模式下执行insert、update、delete操作都会获取buffer。在current模式下如果在高速缓存区发现有新的缓存足够给当前的事务使用,则这些buffer都会被读入了缓存区中。
ROWS: 所有SQL语句返回的记录数目,但是不包括子查询中返回的记录数目。对于select语句,返回记录是在fetch这步,对于insert、update、delete操作,返回记录则是在execute这步。


-----------------------------举例---------------------

tkprof是在cmd下执行!!