优化器

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了优化器相关的知识,希望对你有一定的参考价值。

--CBO主要包含以下组件:
1.查询转换器(Query Transformer):查询转换器的作用就是改变查询语句的形式以产生较好的执行计划.
--四种转换技术:
视图合并(View Merging)、谓词推进(Predicate Pushing)、非嵌套子查询(Subquery Unnesting)和物化视图的查询重写(Query Rewrite with Materialized Views)
--“窥视”(Peeking):用户使用绑定变量时,查询转换器可以“偷窥”绑定变量的实际值。
2.评估器(Estimator)
选择性:是一个大于0小于1的数,0表示没有记录被选定,1表示所有记录都被选定。统计信息和直方图关系到选择性值的准确性。如:name=’Davis’,如果不存在统计信息评估器将根据所用的谓词来指定一个缺省的选择性值,此时评估器会始终认为等式谓词的选择性比不等式谓词小;如果存在统计信息而不存在直方图,此时选择性值为1/count(distinct name);如果存在统计信息也存在直方图,选择性值则为count(name)where name=’Davis’ / count(name)where name is not null。
基数:通常表中的行数称为“基础基数”(Base cardinality);当用WHERE中的条件过滤后剩下的行数称为“有效基数”(Effective cardinality);连接操作之后产生的结果集行数称为“连接基数”(Join cardinality);一个字段DISTINCT之后的行数称为“DISTINCT基数”;“GROUP基数”(Group cardinality)比较特殊,它与基础基数和DISTINCT基数有关,例如:group by colx则GROUP基数就等于基础基数,但是group by colx,coly的GROUP基数则大于max ( distinct cardinality of colx , distinct cardinality of coly )且小于min ( (distinct cardinality of colx * distinct cardinality of coly) , base cardinality)。
成本:就是度量资源消耗的单位。可以理解为执行表扫描、索引扫描、连接、排序等操作所消耗I/O、CPU、内存的数量。
3.计划生成器(Plan Generator)
计划生成器的作用就是生成大量的执行计划,然后选择其中总体成本最低的一个。
--影响优化器模式及目标的HINTS:
ALL_ROWS:意义同OPTIMIZER_MODE=ALL_ROWS。
FIRST_ROWS(n):意义同OPTIMIZER_MODE=FIRST_ROWS_n。
CPU_COSTING:启用CPU成本计算,也就是在总成本中考虑CPU的成本,缺省是启用的。该HINTS是10g中新增加的。
NO_CPU_COSTING:关闭CPU成本计算,也就是在总成本中不考虑CPU的成本,只计算I/O的成本。该HINTS也是10g中新增加的。

--访问路径
访问路径就是从数据库里检索数据的方式。优化器首先检查WHERE子句和FROM子句的条件,确定有哪些访问路径是可用的。然后优化器使用这些访问路径或各访问路径的联合,产生一组可能存在的执行计划,再通过索引、字段、表的统计信息评估每个计划的成本,最后优化器选择成本最低的执行计划所对应的访问路径。
如果SQL语句的FROM子句无SAMPLE或SAMPLE BLOCK,优化器在选择访问路径的时候会优先考虑语句中的HINTS。

--优化器可用的访问路径如下:
--全表扫描(Full Table Scans)
CBO优化器何时会选择全表扫描:
1)无合适的索引。
2)检索表中绝大多数的数据。
3)表非常小。比如,表中的块小于DB_FILE_MULTIBLOCK_READ_COUNT,只需一次I/O。如果这样的表被频繁使用应该alter table table_name storage(buffer_pool keep)。
4)高并行度。如果在表级设置了较高的并行度,如alter table table_name parallel(degree 10),通常会使CBO选择全表扫描。通常建议在语句级用HINTS来实现并行,如/*+full(table_name) parallel(table_name degree)*/。
5)太旧的统计数据。如果表没有进行过分析或很久没有再次分析,CBO可能会错误的认为表含有及少的数据块。
6)在语句中嵌入了全表扫描的HINTS。
--Rowid扫描(Rowid Scans)
Rowid表示行在数据块中的具体位置,Rowid是查找具体行的最快方式。可以在WHERE子句中写入Rowid,但是不推荐这么做。通常都是通过索引来获得Rowid,但如果被检索的行都包含在索引中时,直接访问索引就能得到所需的数据则不会使用Rowid。
--索引扫描(Index Scans)
索引不仅包含被索引的字段值,还包含行的位置标识Rowid,如果语句只检索索引字段,Oracle将直接从索引中读取而不需要通过Rowid去访问表,如果语句通过索引检索其他字段值,则Oracle通过索引获得Rowid从而迅速找到具体的行。
索引扫描类型:
1) 唯一索引扫描(Index Unique Scans)
2) 索引范围扫描(Index Range Scans)
3) 索引降序范围扫描(Index Range Scans Descending)
4) 跳跃式索引扫描(Index Skip Scans)
5) 全索引扫描(Full Index Scans)
6) 快速全索引扫描(Fast Full Index Scans)
7) 索引连接(Index Joins)
--簇扫描(Cluster Scans)
在被索引的簇中,有着相同簇键值的行存储在同一数据块中。执行簇扫描时,首先通过扫描簇索引获得被检索行的Rowid,然后使用Rowid来定位具体的行。
--散列扫描(Hash Scans)
散列扫描就是在一个散列簇中定位数据行。在一个散列簇中,具有相同散列值的行存储在相同的数据块中。在执行散列扫描时,首先通过一个散列函数来获得散列值,然后用散列值在数据块中定位具体行
--表取样扫描(Sample Table Scans)
当FROM子句后带有SAMPLE或SAMPLE BLOCK时,会执行表取样扫描来随机检索表中的数据。
--影响执行计划因素
影响一个连接语句执行计划的四个重要因素是:访问路径、连接方式、连接顺序和成本评估。
--优化器如何处理连接顺序
优化器首先确定连接的表中是否包含其结果只有一行记录的表,如果存在这样的表,优化器在对连接表排序时会把这样的表放在最前端。如果是个外连接,含有(+)操作符的表一定排在不含(+)的表的后面。同理被转换成ANTI-JOIN或SEMI-JOIN的子查询,子查询的表一定排在外部表的后面,但是HASH-ANTI-JOIN和HASH-SEMI-JOIN在一定情况下可以违反此顺序。通常可以用ORDERED来指定连接顺序,但是ORDERED所指定的顺序如果违反了外连接的顺序,则ORDERED将被忽略。
--ordered并发关键字
ORDERED提示强制Oracle按照From子句中表出现的顺序进行表连接。
通过ordered提示,可以避免CBO SQL解析过程中的表连接评估,从而避免Oracle产生错误的执行计划,或者强制Oracle按照我们指定的方式执行。在很多时候,当我们清楚地了解数据结构和数据分布之后,就可以通过ORDERED提示来提高SQL性能。

--一些影响优化器的初始化参数

OPTIMIZER_FEATURES_ENABLE:每个版本的Oracle优化器特性都不相同,特别是做了版本升级以后一定要修改这个参数才可以使用仅被该版本支持的优化器特性。

CURSOR_SHARING:这个参数会将SQL语句中的直接量用变量来替换,存在大批直接量的OLTP系统可以考虑启用这个参数。但是要注意,绑定变量虽然可以使大量的SQL重用,减少分析时间,但是执行计划可能会不理想。通常OLTP系统适用于绑定变量,OLTP系统特点是,SQL运行频繁且时间相对较短,SQL的分析时间比重较大。如果在DSS系统中,SQL运行时间长,相比之下分析时间微不足道,好的执行计划才是最重要的,因此DSS系统不建议使用这个参数。

HASH_AREA_SIZE:这是散列表的存放区域,如果使用散列连接这个参数值不能太小,否则对散列连接性能影响很大。如果是9i建议启动工作区自动管理,然后设置PGA_AGGREGATE_TARGET。

SORT_AREA_SIZE:内存排序区的大小,如果排序时内存区不够会写入磁盘。9i同样建议启动工作区自动管理,然后设置PGA_AGGREGATE_TARGET。

HASH_JOIN_ENABLED:只有启用这个参数,CBO在考虑连接方式的时候才会考虑散列连接。

OPTIMIZER_INDEX_CACHING:这个参数表示被缓存的索引块所占的百分比,可选值的范围是0-100。这个值会影响嵌套循环连接,如果这个值设得较高,CBO将更倾向使用嵌套循环。

OPTIMIZER_INDEX_COST_ADJ:优化器利用这个参数(是个百分比)把索引扫描的成本转换为等价的全表扫描的成本,然后与全表扫描的成本进行比较。缺省值100,表示索引扫描成本与全表扫描成本等价。可选值范围是0-10000。

OPTIMIZER_MAX_PERMUTATIONS:这个初始参数用来设定优化器最多考虑多少种连接顺序,优化器不断的产生可能的表的连接的排列,直到排列数达到参数optimizer_max_permutations为止。一旦优化器停止产生新的排列,它将会从中选择出成本最小的排列。

DB_FILE_MULTIBLOCK_READ_COUNT:这个参数表示在全表扫描或索引快速全扫描时一次I/O读的连续数据块数量(block#连续,且一次I/O不能超过extent)。

OPTIMIZER_MODE:优化器模式。值为:RULE、CHOOSE、ALL_ROWS、FIRST_ROWS_n、FIRST_ROWS。

PARTITION_VIEW_ENABLED:如果设置为TRUE, 该优化器将跳过分区视图中未被请求的分区,该参数还能更改基于成本的优化程序从基础表统计信息计算分区视图统计信息的方式。

QUERY_REWRITE_ENABLE:如果设置为TRUE,优化器将利用可用的物化视图来重写SQL。

以上是关于优化器的主要内容,如果未能解决你的问题,请参考以下文章

Pytorch优化器全总结常用优化器性能对比 含代码

ValueError:未知优化器:优化器

Tensorflow Adam 优化器与 Keras Adam 优化器

Adam优化器

Oracle_sql优化基础——优化器总结

SQL 数据库查询的优化工具及实用