Hints(Oracle)

  • Post author:
  • Post category:其他


Hints(Oracle)

Hins约束优化器行为的一种方式(可以干预优化器,让优化器用我们指定的方式执行)

一般 DBA 做性能分析使用,开发避免使用

可以影响 优化器模式,数据访问,表关联,表连接顺序,并行,sql转换重写

【优化器模式】

1.all_rows 最快方式把整个数据处理完 (场景:报表,聚合查询数据 可以看情况嵌入)

对语句块选择基于开销的优化方法,并获得[最佳吞吐量,使资源消耗最小化]

2.first_rows 指定返回多少行 (场景:分页查询前多少行)

对语句块选择基于开销的优化方法,并获得[最佳响应时间,使资源消耗最小化]

【数据访问】

访问路径相关hints(基于表基于索引)

1.全表扫描 /

+ FULL(TABLE)

/

SELECT /

+FULL(A)

/ * from Demo01 where data_dt=‘2022-01-10’;

SELECT * from Demo01 where data_dt=‘2022-01-10’;

可以从执行计划Cost(cpu)看出差别

多块读:一次I/O,多次读(索引可能不如全表扫描,索引至少2次I/O,定位数据,全表扫描并不是都效率低,取决于数据块的多少)

2.强制使用索引 INDEX / NO_INDEX

3.INDEX_FSS(fss fast full scan 索引 快速的 全部的 扫描 通常用来统计索引的总数)

机制和全表扫描很像,全表可以 多数据块的读 INDEX_FSS也可以且可以并行,只不过INDEX_FSS处理的是索引,索引的数据块比全表更小,效率比全表高

INDEX_RANGE_SCAN(就是正常访问索引) 举例 索引的范围扫描 id>10 从索引是10的键值向后顺序扫,由于是顺序扫就不可以做数据块的读和并行

是一个数据块读的,适合用范围扫描,而且扫描的范围不能太打,否则不如全表扫描

INDEX_FAST_SCAN(FSS) 多数据块的读 举例 10条键值在一个块,尽管是1次I/O,但是读一个块的时间没有读十个块的时间快 一次I/O 读单块肯定比读多块时间短

可以读取多个数据块,适合整个索引的统计

INDEX_SKIP_SCAN 替代全表扫描的一种方式,对于前导数据重复率高的联合索引性能更好

用在 联合索引且第一个字段重复率较高,重复跳过

查询条件里,如果只用到了第二个字段,通常就不会走索引了,但INDEX_SKIP_SCAN仍可以直接使用第二个字段的索引

数据量非常小 INDEX_RANGE_SCAN>INDEX_FAST_SCAN

【结果集关联】这里 结果集=表,实际结果集更准确

外部表 提供数据的表 内部表 被查询的表

3种join的性能不一定哪个最好,优化器选择是根据数学模型算出来决定的

/*+ use_nl(table_1,table_2) */ 指定nest loops方式

NL 机制:从外部表不断地拿数据和内部表比(左面结果集选一条去右边查)

适合场景:1.适合外部表比较小

2.被关联的字段上有索引,索引的键值重复率不是很高 (特别适合)

/*+ use_hash(table_1,table_2) */ 指定使用hash join方式

HJ 机制:会把小一点的表做hash,数据会做一个Hash算法存到内存,内存中就有很多hash列表,即很多结果集分区(做Hash后,bitmap维系哈希区域,值的地址,位计算很快)

内存放不下就会落在Oracle临时表空间 (内存装不下的会溢写到磁盘)

大表也会做Hash,即很多结果集分区

从大的Hash区那一部分数据去小的比对(相同的分区之间做比对)

适合场景:1.适合一个大表一个小表(小表可以都Hash到内存,内存计算速度快)

2.表没索引(做Hash后,效率不受索引影响,受内存中Hash列表影响)

3.返回结果集比较大(相对于NL来说,一个Hash区和Hash区比对)

/

+ use_merge(table_1,table_2)

/ 指定使用merge join方式

MJ 机制:把两个结果集分别排序,然后进行连接 (出现的不是很多,算法比较费资源)

适合场景:1.恰好结果集已经排完顺

【其他】

/

+leading+

/ 表关联顺序

cbo会计算哪张表作为驱动表,会计算所有情况的代价

/

+append+

/ 直接加载的方式插入数据

Oracle的对象都有一个高水位(High water Mark)

传统加载:会在高水位以下找比较空的块插入(Oracle 文件头会标注哪些块允许插数据)

直接加载:跳过高水位,在高水位之上加载,加载后把高水位向上移

对比:传统加载会搜文件头块,定位那些是空的,找到这些数据块,且数据块是分散的,比较耗时,或数据块当前时点有插入操作,还有征用问题

读数据时候会读到高水位的时候代表读动作完成,直接加载在高水位之上,两者不会相交,所以直接加载方式性能较高

Redo问题:有时候会减少Redo 有时候不会(高水位性能影响较多,Redo较少)

当数据库是归档的时候且表的属性是Logging(默认)时,Append是产生Redo的,性能不会显著提高,和No Append性能差不多,

如果表的属性是NOLogging时 Append几乎不产生Redo,会很大提高性能,在非归档模式下无论Logging/NOLogging都不会产生Redo

/

+dynamic sampling+

/ 动态采样级别

级别越高采样数据越多也就越准确,同样消耗的资源也会变多

/

PARALLEL

/ 指定并行度

数据库/表/SQL 都可以设置并行度,这里是针对SQL

/

DRIVING_SITE()

/ 对于分布式,指定操作在哪个节点完成

远程表会传到本地做关联,使用Hint会将本地数据传到远程操作在拿回来

/

+cardinality()+

/ 模拟结果集的数量

做计算的时候”欺骗”优化器,影响表的数量,通常用来模拟一些数据结果集,研究执行计划



版权声明:本文为weixin_45283159原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。