SQL整体优化和调整学习笔记
1.下图是SQL整体处理过程,SQL的响应时间,主要和系统的db block gets/consistent gets/physical read/sort(memory)/sort(disk)相关。

关于OPTIMIZER_MODE(initSID.ora) 优化模式:
Value Means
CHOOSE
A. 这是OPTIMIZER_MODE参数的缺省值,表示优化器会在CBO和RBO间选择.若(SQL所访问
对象的)统计信息有效,则选择CBO,否则将选RBO.
B. 只要在SQL 所访问的表(一个或多个)的数据字典中,存在一个(或多个)统计,则优化器将会选择
CBO方法,并且以最佳吞吐为目标.
C. 若数据字典中只含有部分统计信息,则仍然用CBO,但优化器需在对象(表、索引等)无统计的情
况下去猜测其统计数据,这会导致次优的执行计划(非最优).
D. 若数据字典中未含SQL所访问表的任何统计,则优化器用RBO.
ALL_ROWS
Optimizer 将使用CBO(不管统计信息是否存在),并且将优化目标定为最佳吞吐(即使用最少的资
源执行完成整个语句).
FIRST_ROWS_n
Optimizer 将使用CBO(不管统计信息是否存在),并且将优化目标定为最快时间(best response time)返回结果的前N(N可以为1,10,100,1000)行.
FIRST_ROWS
Optimizer将综合使用成本和启发(heuristics)来找出最快返回结果第一行的执行计划.
注意: 在使用启发(heuristics)时,有可能会导致CBO 生成成本比不使用启发(heuristics)高得多
的执行计划.FIRST_ROWS这个参数主要是为了用于向后兼容和保持原计划的稳定性的.
RULE
Optimizer将使用RBO而不管统计信息是否存在.
optimizer_mode 和 optimizer_goal
可以使用语句:
alter session set optimizer_mode = FIRST_ROW_10来改变当前SESSION的优化模式。
另外设置 optimizer_goal 也和以上有相同效果,都设置optimizer_goal 将覆盖optimizer_mode参数设置。
也可以在语句中加HINTS来实现语句级别的优化模式改变:
/*+All_ROWS(N)*/ ALL_ROWS/CHOOSE/RULE/FIRST_ROWS
CBO的统计信息
可以用DBMS_STATS或ANALYZE(8I以前)对TABLE/INDEX进行完全或部分采样统计物理存储和数据统计属性。
对8I以后建议用DBMS_STATS进行分析,相比而言,DBMS_STAT可以并行进行统计,并可以对分区信息进行统计
对于以后ANALYZE 主要是进行VALIDATE校验对象结构有效性,使用LIST CHAINED ROWS来分析行链接,收集FREELIST BLOCK信息。
当SQL对象有以下特性时,整个SQL会用到CBO,即使optimizer_mode = rule :
Partitioned tables and indexes
Index-organized tables(IOT)
Reverse key indexes
Function-based indexes
SAMPLE clause in a SELECT statement
Parallel query and parallel DML
Star transformations and star joins
Extensible optimizer
Query rewrite with materialized views
Enterprise Manager progress meter
Hash joins
Bitmap indexes and bitmap join indexes
Index skip scans
理解CBO
CBO 在生成SQL 的计划时,会考虑对象的可访问路径和对象的统计信息,才会决定哪个执行计划是最优的.CBO 还会考虑hints(用户置于语句中的优化建议).
以下是CBO执行的步骤:
A. 基于可用的访问路径和hints, Optimizer为SQL语句生成一个有效的计划集合.
B. Optimizer基于SQL语句所访问对象存在数据字典中的统计(即对象的数据分布和存储特性),来评估每个计划的成本.
所谓成本(Cost)就是执行(某个SQL 的)某种计划估计需要使用到多少资源.Optimizer 评估执行所需用到的计算机资源(包括I/O,CPU和内存),根据结果来计算access paths和join orders的成本.成本高的计划比成本低的执行计划需要更长的执行时间.但在使用一个并行计划时,资源的使用并不能直接反映到执行所需要的时间上去.
CBO结构
CBO包含三个主要组件: Query Transformer / Estimator / Plan Generator
CBO的结果如图:

Query transformer
是将已parse好的查询,这个已经parse好的查询包含子查询块,这些块相互嵌套,相互关联。
Query transformer的目的就是改变查询语句的格式降低执行成本,从而生成更优的执行计划。
View Merging /Predicate Pushing/Subquery Unnesting/Query Rewrite with Materialized Views主要为这四种Query transformer转换技术。
View Merging 对于查询中引用到的视图都被parse成独立的Query block,这些本质对应着对立的视图的定义,产生一个视图,而对于OPTIMIZER来说,最简单的办法是对分析视图的Query block,产生SUBPLAN,在整个EXPLAN PLAN中使用SUBPLAN.但这种方法常产生非最优的计划。
Query transformer将VIEW产生的Query block合并到整个SQL中去,绝大部分视图被合并,对应的视图Query block被合并到整个SQL中.
Predicate Pushing 对于那些未合并的视图,Query transformer会加入一些相关query block 从而使这些未合并的视图的执行计划使用索引或有更高的过滤性。
Subquery Unnesting 将多数子查询转化成JOIN从而解除嵌套,已变生成更优的执行计划。对于未解除嵌套的子查询,将单独生成SUBPLAN。并且为提高所有查询计划的执行速度,subplan将被格式化为更有效的方式。
Query Rewrite with Materialized Views
物化视图就象一个查询连同查询结果一起存在于一个表中.当Query Transformer 发现用户查询语句与物化视图的查询相兼容时,用户的查询SQL就会被用物化视图相关的查询来重写. 用这种技术可以提高用户查询的效率,因为物化视图中已存放了很多的查询结果.Query Transformer 会查找与用户查询兼容的物化视图,若找到的话,就用这些物化视图来重构用户查询. 用物化视图来重写用户查询是基于成本的.也就是说假如基于物化视图重写出来的计划成本高于不用物化视图的成本,则Query Transformer将不会用物化视图.
Estimator
Estimator将生成三种不同的衡量值 Selectivity/Cardinality/Cost 这些是相关的
Selectivity:与查询条件相关,过滤出的行数占总记录数的比率,取值0-1之间。假如统计不可用,则会取默认的值。
Cardinality:相关ROWSET的总记录数。
COST :使用的相关工作单元和资源。包括磁盘I/O,CPU使用量,内存工作量
Plan Generator 的主要功能就是根据查询生成多种可行的不同计划,并找出其中成本最低的计划。
包括 join order,join method
理解CBO的Access Paths
Access Paths 就是何种方式从数据库中检索出数据:
FULL TABLE SCAN,INDEX TABLE SCAN,ROWID
主要有以下几种:
Full table scans / Sample table scans / rowid scans/ index scans / cluster scans/ hash scans
Full table scans : 将会扫描所有HWM之下的块,并将行数据与where条件相比较。进行全表扫描时,是按顺序读取数据块的,因次一次I/O读取更多的数据块能提高性能,初始参数DB_FILE_MULTIBLOCK_READ_COUNT就可设置一次I/O读多少块.
Optimizer在下面情况下使用全表扫描:
LACK OF ACCESS PATHS 没有任何可以使用的索引。
LARGE AMOUNT OF DATA :Optimizer会访问多数数据块。
SMALL TABLE :HWM下的块数小于DB_FILE_MULTIBLOCK_READ_COUNT的块数,一次I/O比index range scan 更低。
Old statistics: 表从来没分析过,并且HWM下的块数小于DB_FILE_MULTIBLOCK_READ_COUNT的块数,就认为是小表,走全表扫描,可查看all_tables里的last_anayled 和BLOCKS。
High Degree of Parallelism:当表有很高的并行度时。可查询all_tables里的DEGREE。
Full table scans hint: 全表扫描 /*+Full(tablename)*/
Sample Table Scans : 当查询语句中有sample(占总记录数百分比)或sample block(占总块数百分比)时,将用到 Sample Table Scans .当用到JOIN或远程表时,将不会用Sample Table Scans。
可以先CREATE TABLE AS 然后在引用,也用到CBO。
Rowid Scans :ROWID对应数据的物理地址,从where字句获的或索引获取是最高效的路径
Index Scans: 从属于索引的一个或几个列值检索出对应行的ROWID或其他索引列的值
Index Unique Scans/ Index Range Scans/ Index Range Scans Descending/ Index Skip Scans/ Full Scans/Fast Full Index Scans/Index Joins/Bitmap Joins
Index Unique Scans: 当sql中的where 条件和表上的Unique约束 或 主键约束 相匹配。/*+Index()*/
Index Range Scans : 当查询条件中含一个或多个索引引导列是。
Index Range Scans Descending:和上相同,但是是按降序排列(缺省是按升续排列)/*+Index_Des()*/
Index skip scan :当复合索引的前缀列并未用条件上,并且当第一列只有很少重复值,效率才比较高
Index Full Scan :引用了索引中的某列,可能使用。所需查询列都包含在索引中,索引列至少有一列有NOT NULL 约束,所的结果是按索引排序。只用于CBO。
Index Fast Full Scan : 查询所需列都在索引列中,并不是按索引排序,并行对整个索引做MUTIBLOOCK read, 设置初始参数 OPTIMIZER_FEATURES_ENABLE 或 INDEX_FFS hint ,index fast full Scan 不能用于位图索引。
Index join : 是指将多个索引中的列 通过hash连接在一起。所需的列 全在索引中 无须访问表。Index join 只能用于CBO。 可以设置参数Index join。设置参数OPTIMIZER_FEATURE_ENABLE 或 INDEX_JOIN 这种访问模式。
Bitmap Joins:用于CBO .9I Enterprise Edition可以用。Standard Edition 中无此功能。
Cluster Scans : 用于indexed cluster中,
Hash Scans:用于hash cluster中
Understanding Joins
Nested loop join
Sort merge join
Hash join(这种join模式在RBO中不能使用)
Cluster join
Nested Loop Joins : 当小的结果集需连接且连接条件可高效地访问第二个表时,nested loop join是很有效的./*+ USE_NL(a b)*/
Nested Loop Outer Joins:
Hash Join: Optimizer会在两个表用非等价连接,且满足以下条件之一时使用hash join,需要连接的数据量巨大;或表的大多数需要连接。/*+ USE_HASH(a b)*/
Hash Outer Joins:
Sort Merge Joins:Sort merge joins可用于将两个不相关的sources连接到一起./*+USE_MERGE(a b)*/
Sort Merge Outer Joins:
Cartesian Joins:当多个表间无任何连接条件作连接时,使用的就是Cartesian(笛卡尔) join./*+order+*/
Full Outer Joins:
,