我所学习的数据库知识总结!~

本文深入探讨了SQL优化的重要性及具体方法,详细介绍了Oracle与SQL Server的优化器模式、执行计划生成过程及数据访问方式,适合数据库管理员及开发人员阅读。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


/**************************************************************************************************************************************************************************************/

写在前面:

        第一次写技术博客,先把以前学到的一些知识贴出来吧,这个总结还是一年多前弄的,当时是为了零基础做一个sql优化的需求,在看了一些网上的文章和资料后发现,网上很多的SQL优化或者数据库优化的资料,大都在告诉你怎么去做,但是没有说为什么这样做,而在我真正去做优化的工作时发现,所谓的优化很少有统一适用的规则,更多的时候是需要分析实际情况,而了解数据库的一些基本知识才能更好的去分析问题。

        因为当时的环境是正在使用Sql Server,但是项目所做的下一个工作是希望移植到ORACLE上,并且ORACLE的资料更多些,另外ORACLE与Sql Server在有些处理上有类似的地方,所以下面就出现了ORACLE与Sql Server的内容混杂在一起的情况。

        最后,这个总结也恰是我在零基础的时候慢慢收集起来的,发在这里留以后方便查阅,但是由于时间有些长久,无法确定很多资料的原始出处了,请原作者原谅!~


/**************************************************************************************************************************************************************************************/


Oracle的优化器共有3种模式:RULE (基于规则)、COST(基于成本)、CHOOSE(基于选择)。

由optimizer_mode初始化参数决定的(show parameter OPTIMIZER_MODE)。

该参数可能的取值为:

first_rows_[1 | 10 | 100 | 1000] | first_rows |all_rows | choose | rule。

 

(一)、基于规则的优化方式(Rule-Based Optimization,简称为RBO)

基于规则的优化器中采用启发式的方法(Heuristic Approach)或规则(Rules)来生成执行计划。


(二)、基于代价的优化方式(Cost-Based Optimization,简称为CBO)

查询耗费的资源可以被分成3个基本组成部分:I/O代价、CPU代价、network代价。


First Rows: 它与Choose方式是类似的,所不同的是当一个表有统计信息时,它将是以最快的方式返回查询的最先的几行,从总体上减少了响应时间

All Rows: all_rows是oracle优化器默认的模式,它将选择一种在最短时间内返回所有数据的执行计划,它将基于整体成本的考虑.

First_rows_n: first_rows_n是根据成本而不是基于硬编码的规则来选择执行计划.n可以是1,10,100,1000或者直接用first_rows(n) hint指定任意正数.这里的n是我们想获取结果集的前n条记录,这种需求在很多分页语句的需求中会碰到. 

必须经常运行analyze命令,以增加数据库中的对象统计信息(object statistics)的准确性。

 

不管optimizer_mode参数如何设置,只要满足下面3个条件,就一定使用CBO。

1)   如果使用IndexOnly Tables(IOTs), 自动使用CBO。

2)   Oracle 7.3以后,如果表上的Paralledegree option设为>1, 则自动使用CBO, 而不管是否用rule hints。

3)   除rlue以外的任何hints都将导致自动使用CBO来执行语句。

 

(三)、在缺省情况下,Oracle采用CHOOSE优化器,如果数据字典中包含被引用的表的统计数据,即引用的对象已经被分析,则就使用CBO优化器,否则为RBO优化器。

 

 

 

Sql Server的物理存储:

Sql Server的表使用如下两种方法组织其数据页:

聚集表:聚集表就是具有聚集索引的表,它基于聚集索引键按顺序存储数据行,索引按B树索引结构实现。B树基于聚集索引键值对行进行快速检索。每级索引的页链接在双向链表中,但使用键值在各级间进行导航。数据行本身构成聚集索引的最低级别。

 

堆集:堆集是没有聚集索引的表,不按任何特殊顺序存储数据行。数据页不在链表内链接。非聚集索引有一个与聚集索引中相似的B树索引结构,但是他对数据行的顺序不起作用,其最低行包含非聚集索引的键值,每个键值项都有指针指向包含该键值的数据行。对于堆集,该指针是指向行的指针,对于聚集表,则是聚集索引键。该指针叫做行定位器。

 


SQL Server 的数据文件中有一类是IAM,即索引分配映射表,它存储有关表和索引所使用的扩展盘区信息。

一个堆集在sysindexes内有一行,其indid=0。FirstIAM列指向指向表的数据页集合的IAM链。服务器使用IAM页查找数据页集合内的页。通过扫描IAM页,可以对堆集进行表扫描或串行读,以找到这个堆集的页的扩展盘区。所以,对于没有任何索引的堆集,不管做什么样的查询,服务器都必须对对表进行一次扫描。哪怕只返回一行,其IO数都是一样的,即表的行数。


某个表和视图的聚集索引在sysindexes内有一行,其indid=1。root列指向聚集索引B树的顶端。服务器使用B树查找数据页。SQL Server沿着聚集索引浏览以找到聚集索引键对应的行。为找到键的范围,SQL Server浏览索引以找到这个范围的起始值,然后用向前或向后页扫描数据页。为找到数据页链的页首,SQL Server从索引的根节点开始沿着最左边的指针进行扫描。所以,如果用聚集索引查找数据,如果只返回一行,那么其IO数,就是B树的顶端到键值所在数据行的深度,简记为D。如果返回多行,则需要再加上符合条件的页数,简记为P。总的IO数为D+P。


某个表或视图的非聚集索引在索引在sysindexes内也有一行,其indid值从2到250,root列指向非聚集索引B树的顶端。SQL Server在查找数据时,服务器先使用与聚集索引相同的查找方法找到该索引的行定位器——Bookmark,然后通过行定位器来找到所需要的数据,这种通过行定位器查找数据的方式就是Bookmark Lookup。如果索引所在的表是堆集,那么Sql Server使用行指针来找到数据。所以,这种情况下,返回1行的IO数是找到行定位器为止的B树的深度D+1。而如果返回多行,则IO数为D+所有满足条件的索引页的页数P+返回行数H。如果索引所在的表是聚集,那么Sql Server使用聚集索引的键来找到数据。所以,这种情况下,返回1行的IO数是找到行定位其为止的B树的深度D+找到聚集索引的键的B树的深度D1。返回多行的IO数则为D+P+H*D1。


在基于非聚集索引查找数据时,还有另外一种情形,那就是如果需要查找的数据列就包含于索引的键值中,或者包含于索引的键值+聚集索引的键值中,那么就不会发生Bookup Lookup,因为找到索引项,就已经找到所需的数据了,没有必要再到数据行去找了。这种情况,叫做索引覆盖。

还可以通过将包含列(称为非键列)添加到索引的叶级,可以扩展非聚集索引的功能。键列存储在非聚集索引的所有级别,而非键列仅存储在叶级别

 


SQL Server索引查找数据方式:

聚集索引中,叶节点包含基础表的数据页。根节点和中间级节点包含存有索引行的索引页。每个索引行包含一个键值和一个指针,该指针指向 B 树上的某一中间级页或叶级索引中的某个数据行。每级索引中的页均被链接在双向链接列表中。

 

非聚集索引中的每个索引行都包含非聚集键值和行定位符。此定位符指向聚集索引或堆中包含该键值的数据行。

非聚集索引行中的行定位器或是指向行的指针,或是行的聚集索引键,如下所述:

如果表是堆(意味着该表没有聚集索引),则行定位器是指向行的指针。该指针由文件标识符 (ID)、页码和页上的行数生成。整个指针称为行 ID (RID)。

如果表有聚集索引或索引视图上有聚集索引,则行定位器是行的聚集索引键。如果聚集索引不是唯一的索引,SQL Server 将添加在内部生成的值(称为唯一值)以使所有重复键唯一。此四字节的值对于用户不可见。仅当需要使聚集键唯一以用于非聚集索引中时,才添加该值。SQL Server 通过使用存储在非聚集索引的叶行内的聚集索引键搜索聚集索引来检索数据行

 

 


逻辑上,oracle用如下存取方法访问数据

1——全表扫描(Full Table Scans, FTS),最高水线处(high water mark, HWM,标识表的最后一个数据块),一个多块读操作可以使一次I/O能读取多块数据块(db_block_multiblock_read_count参数设定),而非只读取一个数据块,这极大的减少了I/O总次数,提高了系统的吞吐量,所以利用多块读的方法可以高效实现全表扫描,而且只有在全表扫描的情况下才能使用多块读操作。在这种访问模式下,每个数据块只被读一次。由于HWM标识最后一块被读入的数据,而delete操作不影响HWM值,所以一个表的所有数据被delete后,其全表扫描的时间不会有改善,一般需要使用truncate命令来使HWM值归为0。幸运的是oracle 10G后,可以人工收缩HWM的值。


2——通过ROWID的表存取(Table Access by ROWID或rowidlookup)

ROWID由OBJECT(6位)、FILE(3位)、BLOCK(5位)、ROW NUMBER(4位)构成。

一次I/O只能读取一个数据块。

通过ROWID来存取数据可以快速定位到目标数据上,是Oracle存取单行数据的最快方法。


3——索引扫描(Index Scan或indexlookup)

(1)索引唯一扫描(indexunique scan) 通过唯一索引查找只返回一行

(2)索引范围扫描(indexrange scan)

       (a) 在唯一索引列上使用了range操作符(> < <> >= <= between)

(b) 在组合索引上,只使用部分列进行查询,导致查询出多行

(c) 对非唯一索引列上进行的任何查询。

(3)索引全扫描(indexfull scan)

全索引扫描只在CBO模式下才有效。CBO根据统计数值得知进行全索引扫描比进行全表扫描更有效时,才进行全索引扫描,而且此时查询出的数据都必须从索引中可以直接得到。

(4)索引快速扫描(index fast full scan)

扫描索引中的所有的数据块,与index full scan很类似,但是一个显著的区别就是它不对查询出的数据进行排序,即数据不是以排序顺序被返回。在这种存取方法中,可以使用多块读功能,也可以使用并行读入,以便获得最大吞吐量与缩短执行时间。

 

 

 

表连接方式:

(1)排序--合并连接 (Sort Merge Join (SMJ) ):两边分别先选择再按照join字段进行排序再组合

(2)嵌套循环(Nested Loops (NL) )

Oracle读取row source1中的每一行,然后在rowsourc2中检查是否有匹配的行,所有被匹配的行都被放到结果集中,然后处理row source1中的下一行。这是从连接操作中可以得到第一个匹配行的最快的方法之一,这种类型的连接可以用在需要快速响应的语句中,以响应速度为主要目标。

可以先返回已经连接的行,而不必等待所有的连接操作处理完才返回数据,这可以实现快速的响应时间。

(3)哈希连接(Hash Join)

较小的rowsource被用来构建hash table与bitmap,第2个row source被用来被hashed,并与第一个row source生成的hashtable进行匹配,以便进行进一步的连接。Bitmap被用来作为一种比较快的查找方法,来检查在hash table中是否有匹配的行。

只能用于等值连接中,只能用在CBO优化器中,需要设置HASH_JOIN_ENABLED=TRUE,缺省情况下该参数为TRUE,另外,还要设置hash_area_size参数,以使哈希连接高效运行

(4)笛卡儿乘积(CartesianProduct)

 

 

优化器使用:

Description                                            对象是否被分析             优化器的类型

~~~~~~~~~~~                                     ~~~~~~~~~~~~                    ~~~~~~~~~

Non-RBO Object(Eg:IOT)                          n/a                                    #1

Parallelism > 1                                           n/a                                   #1

RULE hint                                                 n/a                                   RULE

ALL_ROWS hint                                      n/a                                   ALL_ROWS

FIRST_ROWS hint                                   n/a                                    FIRST_ROWS

*Other Hint                                                n/a                                   #1

OPTIMIZER_GOAL=RULE                      n/a                                    RULE

OPTIMIZER_GOAL=ALL_ROWS           n/a                                    ALL_ROWS

OPTIMIZER_GOAL=FIRST_ROWS      n/a                                    FIRST_ROWS

OPTIMIZER_GOAL=CHOOSE                NO                            RULE

OPTIMIZER_GOAL=CHOOSE                YES                          ALL_ROWS

(a)#1 表示除非OPTIMIZER_GOAL 被设置为FIRST_ROWS,否则将使用ALL_ROWS。在PL/SQL中,则一直是使用ALL_ROWS 。

(b)*OtherHint 表示是指除RULE、ALL_ROWS 和FIRST_ROWS以外的其它提示 。

 

 



当一个Oracle实例接收一条sql后:

1、Create a Cursor 创建游标

2、Parse the Statement 分析语句

3、Describe Results of a Query 描述查询的结果集

4、Define Output of a Query 定义查询的输出数据

5、Bind Any Variables 绑定变量

6、Parallelize the Statement 并行执行语句

7、Run the Statement 运行语句

8、Fetch Rows of a Query 取查询出来的行

9、Close the Cursor 关闭游标

 


DML 语句的处理

每种类型的语句都需要如下阶段:

• 第1步: Create a Cursor 创建游标

• 第2步: Parse the Statement 分析语句

• 第5步: Bind Any Variables 绑定变量

• 第7步: Run the Statement 运行语句

• 第9步: Close the Cursor 关闭游标

如果使用了并行功能,还会包含下面这个阶段:

• 第6步: Parallelize the Statement并行执行语句

 

如果是查询语句,则需要几个额外的步骤,如图所示:

• 第3步: Describe Results of a Query 描述查询的结果集

• 第4步: Define Output of a Query 定义查询的输出数据

• 第8步: Fetch Rows of a Query取查询出来的行


 

 

1:创建游标(Create a Cursor)

由程序接口调用创建一个游标(cursor)。任何SQL语句都会创建它,特别在运行DML语句时,都是自动创建游标的,不需要开发人员干预。多数应用中,游标的创建是自动的。然而,在预编译程序(pro*c)中游标的创建,可能是隐含的,也可能显式的创建。在存储过程中也是这样的。

2:分析语句(Parse the Statement)

在语法分析期间,SQL语句从用户进程传送到Oracle,SQL语句经语法分析后,SQL语句本身与分析的信息都被装入到共享SQL区。在该阶段中,可以解决许多类型的错误。

 

语法分析分别执行下列操作:

翻译SQL语句,验证它是合法的语句,即书写正确

实现数据字典的查找,以验证是否符合表和列的定义

在所要求的对象上获取语法分析锁,使得在语句的语法分析过程中不改变这些对象的定义

验证为存取所涉及的模式对象所需的权限是否满足

决定此语句最佳的执行计划

将它装入共享SQL区

对分布的语句来说,把语句的全部或部分路由到包含所涉及数据的远程节点

* 以上任何一步出错误,都将导致语句报错,中止执行。

 

只有在共享池中不存在等价SQL语句的情况下,才对SQL语句作语法分析。在这种情况下,数据库内核重新为该语句分配新的共享SQL区,并对语句进行语法分析。进行语法分析需要耗费较多的资源,所以要尽量避免进行语法分析,这是优化的技巧之一。

语法分析阶段包含了不管此语句将执行多少次,而只需分析一次的处理要求。Oracle只对每个SQL语句翻译一次,在以后再次执行该语句时,只要该语句还在共享SQL区中,就可以避免对该语句重新进行语法分析,也就是此时可以直接使用其对应的执行计划对数据进行存取。这主要是通过绑定变量(bind variable)实现的,也就是我们常说的共享SQL的概念。

虽然语法分析验证了SQL语句的正确性,但语法分析只能识别在SQL语句执行之前所能发现的错误(如书写错误、权限不足等)。因此,有些错误通过语法分析是抓不到的。例如,在数据转换中的错误或在数据中的错(如企图在主键中插入重复的值)以及死锁等均是只有在语句执行阶段期间才能遇到和报告的错误或情况。

 

3:描述查询结果(Describe Results of a Query)

描述阶段只有在查询结果的各个列是未知时才需要;例如,当查询由用户交互地输入需要输出的列名。在这种情况要用描述阶段来决定查询结果的特征(数据类型,长度和名字)。

4:定义查询的输出数据(Define Output of a Query)

在查询的定义阶段,你指定与查询出的列值对应的接收变量的位置、大小和数据类型,这样我们通过接收变量就可以得到查询结果。如果必要的话,Oracle会自动实现数据类型的转换。这是将接收变量的类型与对应的列类型相比较决定的。

 

5:绑定变量(Bind Any Variables)

Oracle知道了SQL语句的意思,但仍没有足够的信息用于执行该语句。Oracle 需要得到在语句中列出的所有变量的值,这个过程就叫绑定变量(binding variables)

程序必须指出可以找到该数值的变量名(该变量被称为捆绑变量,变量名实质上是一个内存地址,相当于指针)。应用的最终用户可能并没有发觉他们正在指定捆绑变量,因为Oracle 的程序可能只是简单地指示他们输入新的值,其实这一切都在程序中自动做了。

因为你指定了变量名,在你再次执行之前无须重新捆绑变量。你可以改变绑定变量的值,而Oracle在每次执行时,仅仅使用内存地址来查找此值。

如果Oracle 需要实现自动数据类型转换的话(除非它们是隐含的或缺省的),你还必须对每个值指定数据类型和长度。关于这些信息可以参考oracle的相关文档,如OracleCall Interface Programmer's Guide

6:并行执行语句(Parallelize the Statement )

ORACLE 可以在SELECTs,INSERTs, UPDATEs, MERGEs, DELETEs语句中执行相应并行查询操作,对某些DDL操作,如创建索引、用子查询创建表、在分区表上的操作,可以执行并行操作。并行化可导致多个服务器进程(oracle server processes)为同一个SQL语句工作,使该SQL语句可以快速完成,但是会耗费更多的资源,所以除非很有必要,否则不要使用并行查询。

 

7:执行语句(Run the Statement)

此时,Oracle拥有所有需要的信息与资源,可以真正运行SQL语句了。如果该语句为SELECT查询或INSERT语句,则不需要锁定任何行,因没有数据需要被改变。如果语句为UPDATE或DELETE语句,则该语句影响的所有行都被锁定,防止该用户提交或回滚之前,别的用户对这些数据进行修改。这保证了数据的一致性。

对于某些语句,你可以指定执行的次数,这称为批处理(array processing)。指定执行N次,则绑定变量与定义变量被定义为大小为N的数组的开始位置,这种方法可以减少网络开销,也是优化的技巧之一。

8:取出查询的行(Fetch Rows of a Query)

在fetch阶段,行数据被取出来,每个后续的存取操作检索结果集中的下一行数据,直到最后一行被取出来。上面提到过,批量的fetch是优化的技巧之一。

9:关闭游标(Close the Cursor)

SQL语句处理的最后一个阶段就是关闭游标。

 

 

 

SQL 语句的执行步骤:

1、语法分析 ,分析语句的语法是否符合规范,衡量语句中各表达式的意义。

2、语义分析 ,检查语句中涉及的所有数据库对象是否存在,且用户有相应的权限。

3、视图转换,将涉及视图的查询语句转换为相应的对基表查询语句。

4、表达式转换, 将复杂的 SQL 表达式转换为较简单的等效连接表达式。

5、选择优化器,不同的优化器一般产生不同的“执行计划”

6、选择连接方式, ORACLE 有三种连接方式,对多表连接ORACLE 可选择适当的连接方式。

7、选择连接顺序, 对多表连接 ORACLE 选择哪一对表先连接,选择这两表中哪个表做为源数据表。

8、选择数据的搜索路径, 根据以上条件选择合适的数据搜索路径,如是选用全表搜索还是利用索引或是其他的方式。

9、运行“执行计划”

 

当执行查询时,ORACLE采用了内部的操作.下表显示了几种重要的内部操作.

ORACLE Clause

内部操作

ORDER BY

SORT ORDER BY

UNION

UNION-ALL

MINUS

MINUS

INTERSECT

INTERSECT

DISTINCT,MINUS,INTERSECT,UNION

SORT UNIQUE

MIN,MAX,COUNT

SORT AGGREGATE

GROUP BY

SORT GROUP BY

ROWNUM

COUNT or COUNT STOPKEY

Queries involving Joins

SORT JOIN,MERGE JOIN,NESTED LOOPS

CONNECT BY

CONNECT BY

 

 

查询优化器生成执行计划要做更多的工作,大概分为3部分:

首先,根据传入的查询语句文本,解析表名称、存储过程名称、视图名称等。然后基于逻辑数据操作生成代表查询文本的树。

第二步是优化和简化,比如说将子查询转换成对等的连接、优先应用过滤条件、删除不必要的连接(比如说有索引,可能不需要引用原表)等。

第三步根据数据库中的统计信息,进行基于成本(Cost-based)的评估。

 

 

执行计划所缓存的对象分为4类,分别是:

1、编译后的计划:编译的执行计划和执行计划的关系就和MSIL和C#的关系一样。

2、执行上下文:在执行编译的计划时,会有上下文环境。因为编译的计划可以被多个用户共享,但查询需要存储SET信息以及本地变量的值等,因此上下文环境需要对应执行计划进行关联。执行上下文也被称为Executable Plan。

3、游标:存储的游标状态类似于执行上下文和编译的计划的关系。游标本身只能被某个连接使用,但游标关联的执行计划可以被多个用户共享。

4、代数树:代数树(也被称为解析树)代表着查询文本。正如我们之前所说,查询分析器不会直接引用查询文本,而是代数树。这里或许你会有疑问,代数树用于生成执行计划,这里还缓存代数树干毛啊?这是因为视图、Default、约束可能会被不同查询重复使用,将这些对象的代数树缓存起来省去了解析的过程。

 

 

 

分析执行计划:

产生执行计划:

1).Sql> set autotrace on

Sql> select *from dual;

       执行完语句后,会显示explainplan 与 统计信息。

这个语句的优点就是它的缺点,这样在用该方法查看执行时间较长的sql语句时,需要等待该语句执行成功后,才返回执行计划,使优化的周期大大增长。

       如果不想执行语句而只是想得到执行计划可以采用:Sql> set autotrace traceonly

       这样,就只会列出执行计划,而不会真正的执行语句,大大减少了优化时间。虽然也列出了统计信息,但是因为没有执行语句,所以该统计信息没有用处,如果执行该语句时遇到错误,解决方法为:

a. 在要分析的用户下: Sqlplus > @?\rdbms\admin\utlxplan.sql

b. 用sys用户登陆

Sqlplus > @?\sqlplus\admin\plustrce.sql

Sqlplus > grantplustrace to user_name;      -- user_name是上面所说的分析用户

 

2).用explain plan命令

(1)  sqlplus > @ ?\rdbms\admin\utlxplan.sql

(2)  sqlplus > explain plan set statement_id =’???’ for select    

      ………………

注意:

       此方法时,并不执行sql语句,所以只会列出执行计划,不会列出统计信息,并且执行计划只存在plan_table中。所以该语句比起setautotrace traceonly可用性要差。需要用下面的命令格式化输出,所以这种方式我用的不多:

 

setlinesize 150

setpagesize 500

colPLANLINE for a120

SELECTEXECORD EXEC_ORDER, PLANLINE

FROM(SELECT PLANLINE, ROWNUM EXECORD, ID, RID

FROM(SELECT PLANLINE, ID, RID, LEV

FROM(SELECT lpad(' ',2*(LEVEL),rpad(' ',80,' '))||

OPERATION||''|| -- Operation

DECODE(OPTIONS,NULL,'','('||OPTIONS|| ') ')|| -- Options

DECODE(OBJECT_OWNER,null,'','OF'''|| OBJECT_OWNER||'.')|| -- Owner

DECODE(OBJECT_NAME,null,'',OBJECT_NAME||''' ')|| -- Object Name

DECODE(OBJECT_TYPE,null,'','('||OBJECT_TYPE||') ')|| -- Object Type

DECODE(ID,0,'OPT_MODE:')||-- Optimizer

DECODE(OPTIMIZER,null,'','ANALYZED','',OPTIMIZER)||

DECODE(NVL(COST,0)+NVL(CARDINALITY,0)+NVL(BYTES,0),

0,null,'(COST='||TO_CHAR(COST)||',CARD='||

TO_CHAR(CARDINALITY)||',BYTES='||TO_CHAR(BYTES)||')')

PLANLINE,ID, LEVEL LEV,

(SELECTMAX(ID)

FROMPLAN_TABLE PL2

CONNECTBY PRIOR ID = PARENT_ID

AND PRIORSTATEMENT_ID = STATEMENT_ID

STARTWITH ID = PL1.ID

ANDSTATEMENT_ID = PL1.STATEMENT_ID) RID

FROMPLAN_TABLE PL1

CONNECTBY PRIOR ID = PARENT_ID

AND PRIORSTATEMENT_ID = STATEMENT_ID

STARTWITH ID = 0

ANDSTATEMENT_ID = 'aaa')

ORDER BYRID, -LEV))

ORDER BYID;

 

SELECT ADDRESS,substr(SQL_TEXT,1,20) Text, buffer_gets, executions, buffer_gets/executions AVGFROM v$sqlarea WHERE executions>0 AND buffer_gets > 100000 ORDER BY 5;

 

 


3).用dbms_system存储过程生成执行计划

       使用dbms_system存储过程可以跟踪另一个会话发出的sql语句,并记录所使用的执行计划,而且还提供其它对性能调整有用的信息。这种方法是对SQL进行调整比较有用的方式之一,有些情况下非它不可。

 

 

分析示例

假如Query Plan给出的是下面的形式,则表明使用的是CBO优化器,此处的cost表示优化器认为该执行计划的代价: SELECT STATEMENT Optimizer=CHOOSE (Cost=1234 Card=1 Bytes=14)

 

假如执行计划中给出的是类似下面的信息,则表明是使用RBO优化器,因为cost部分的值为空,或者压根就没有cost部分。

SELECT STATEMENTOptimizer=CHOOSE Cost=

SELECT STATEMENTOptimizer=CHOOSE

 

SQL> SELECT *FROM LARGE_TABLE where USERNAME = ‘TEST’;

Query Plan    -----------------------------------------

SELECT STATEMENTOptimizer=CHOOSE (Cost=1234 Card=1 Bytes=14)

TABLE ACCESS FULLLARGE_TABLE [:Q65001] [ANALYZED]

 

如果Optimizer=ALL_ROWS| FIRST_ROWS|FIRST_ROWS_n,则使用的是CBO优化器;

如果Optimizer=RULE,则使用的是RBO优化器。

 

cost属性的值是一个在oracle内部用来比较各个执行计划所耗费代价的值,从而使优化器可以选择最好的执行计划。不同语句的cost值不具有可比性,只能对同一个语句的不同执行计划的cost值进行比较。

[:Q65001] 表明该部分查询是以并行方式运行的。里面的数据表示这个操作是由并行查询的一个slave进程处理的,以便该操作可以区别于串行执行的操作。

 

[ANALYZED] 表明操作中引用的对象被分析过了,在数据字典中有该对象的统计信息可以供CBO使用。


/**************************************************************************************************************************************************************************************/



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值