博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
讨论ALL_ROWS模式和FIRST_ROWS模式
阅读量:4942 次
发布时间:2019-06-11

本文共 8364 字,大约阅读时间需要 27 分钟。

    在CBO的优化模式下,我们可以使用optimizer_mode参数控制优化模式。主要有两种模式,一种是ALL_ROWS模式,另外一种是FIRST_ROWS模式。

    ALL_ROWS模式适用场景:希望优化程序给出一种尽快得到全部记录的执行计划,目标是增加系统的吞吐量。

    FIRST_ROWS模式适用场景:希望优化程序给出一种可以迅速的得到第一行的执行计划,目标是减少系统的响应时间。

    两种模式需要具体场景具体分析,比如常见的Web应用,很少有一次性得到全部记录的情况,都是分多页交互的响应操作者,因此默认的ALL_ROWS模式就不太合适了,应该考虑使用FIRST_ROWS模式进行优化。又如,我们想要生成全部数据的报表,那么默认的ALL_ROWS模式就比较的合适。

    下面通过实验来比较all_rows和first_rows对执行计划的影响:

  1.实验环境:

  操作系统:rhel 5.4 x32

  数据库:oracle 11.2.0.1.0

  2.首先我们创建一个具有dba权限的用户jack_lin,default_tablespace使用默认的users。

1 SQL> conn /as sysdba2 Connected.3 SQL> create user jack_lin identified by jack;4 User created.5 SQL> grant dba to jack_lin;6 Grant succeeded.

  3.创建该实验需要用到的一张表。

1 SQL> conn jack_lin/jack; 2 Connected. 3 SQL> create table test(id number,name varchar2(10)); 4 Table created. 5 SQL> insert into test values(100,'aaaa'); 6 1 row created. 7 SQL> insert into test values(200,'bbbb'); 8 1 row created. 9 SQL> insert into test values(300,'cccc');10 1 row created.11 SQL> insert into test values(400,'dddd');12 1 row created.13 SQL> commit;14 Commit complete.

  4.在没有索引的情况比较:

  首先来看FIRST_ROWS的效果,为了保证CBO执行计划的准确,我们需要analyze一下表。

1 SQL> alter session set optimizer_mode=first_rows; 2  3 Session altered. 4  5 SQL> analyze table test compute statistics; 6  7 Table analyzed. 8  9 SQL> set autotrace trace exp;10 SQL> select * from test where name='aaaa';11 12 Execution Plan13 ----------------------------------------------------------14 Plan hash value: 135708102015 16 --------------------------------------------------------------------------17 | Id  | Operation      | Name | Rows  | Bytes | Cost (%CPU)| Time     |18 --------------------------------------------------------------------------19 |   0 | SELECT STATEMENT  |     |     1 |     6 |     3   (0)| 00:00:01 |20 |*  1 |  TABLE ACCESS FULL| TEST |     1 |     6 |     3   (0)| 00:00:01 |21 --------------------------------------------------------------------------22 23 Predicate Information (identified by operation id):24 ---------------------------------------------------25 26    1 - filter("NAME"='aaaa')

  由于表上没有索引,所以只有一种选择,全表扫描。

  现在再看一下ALL_ROWS的情况:

1 SQL> alter session set optimizer_mode=all_rows; 2  3 Session altered. 4  5 SQL> select * from test where name='aaaa'; 6  7 Execution Plan 8 ---------------------------------------------------------- 9 Plan hash value: 135708102010 11 --------------------------------------------------------------------------12 | Id  | Operation      | Name | Rows  | Bytes | Cost (%CPU)| Time     |13 --------------------------------------------------------------------------14 |   0 | SELECT STATEMENT  |     |     1 |     6 |     3   (0)| 00:00:01 |15 |*  1 |  TABLE ACCESS FULL| TEST |     1 |     6 |     3   (0)| 00:00:01 |16 --------------------------------------------------------------------------17 18 Predicate Information (identified by operation id):19 ---------------------------------------------------20 21    1 - filter("NAME"='aaaa')

  通过上面的简单举例比较,可以看到在表上没有索引,当数据量很少,并且值唯一的情况下,两种模式的效果是一样的。

  5.在有索引的情况下比较:

  创建索引,并执行在FIRST_ROWS的操作

1 SQL> create index ind_test on test(name); 2  3 Index created. 4  5 SQL> analyze index ind_test compute statistics; 6  7 Index analyzed. 8  9 SQL> analyze table test compute statistics;10 11 Table analyzed.12 13 SQL>  select /*+ first_rows */* from test where name='aaaa';14 15 Execution Plan16 ----------------------------------------------------------17 Plan hash value: 385646689718 19 ----------------------------------------------------------------------------------------20 | Id  | Operation            | Name     | Rows  | Bytes | Cost (%CPU)| Time     |21 ----------------------------------------------------------------------------------------22 |   0 | SELECT STATEMENT        |           |     1 |     6 |     2     (0)| 00:00:01 |23 |   1 |  TABLE ACCESS BY INDEX ROWID| TEST     |     1 |     6 |     2     (0)| 00:00:01 |24 |*  2 |   INDEX RANGE SCAN        | IND_TEST |     1 |       |     1     (0)| 00:00:01 |25 ----------------------------------------------------------------------------------------26 27 Predicate Information (identified by operation id):28 ---------------------------------------------------29 30    2 - access("NAME"='aaaa')

 

  设置成ALL_ROWS的情况:

1 SQL> select /*+ all_rows */ * from test where name='aaaa'; 2  3 Execution Plan 4 ---------------------------------------------------------- 5 Plan hash value: 3856466897 6  7 ---------------------------------------------------------------------------------------- 8 | Id  | Operation            | Name     | Rows  | Bytes | Cost (%CPU)| Time     | 9 ----------------------------------------------------------------------------------------10 |   0 | SELECT STATEMENT        |           |     1 |     6 |     2     (0)| 00:00:01 |11 |   1 |  TABLE ACCESS BY INDEX ROWID| TEST     |     1 |     6 |     2     (0)| 00:00:01 |12 |*  2 |   INDEX RANGE SCAN        | IND_TEST |     1 |       |     1     (0)| 00:00:01 |13 ----------------------------------------------------------------------------------------14 15 Predicate Information (identified by operation id):16 ---------------------------------------------------17 18    2 - access("NAME"='aaaa')

   通过上面的演示可以看到两种模式都走了索引,目前来看一切正常。

  6.现在通过insert into test select * from test;往test表中反复插入记录,注意记录大部分是重复的,其实只有四条,各占1/4。

1 set autotrace off; 2 SQL> insert into test select * from test; 3  4 16384 rows created. 5 SQL> analyze table test compute statistics; 6  7 Table analyzed. 8 SQL> analyze index ind_test compute statistics; 9 10 Index analyzed.11 12 SQL> alter session set optimizer_mode=first_rows;13 14 Session altered.15 16 SQL> set autotrace trace exp;17 SQL> select * from test where name='aaaa';18 19 Execution Plan20 ----------------------------------------------------------21 Plan hash value: 385646689722 23 ----------------------------------------------------------------------------------------24 | Id  | Operation            | Name     | Rows  | Bytes | Cost (%CPU)| Time     |25 ----------------------------------------------------------------------------------------26 |   0 | SELECT STATEMENT        |           |  8192 | 49152 |    87     (0)| 00:00:02 |27 |   1 |  TABLE ACCESS BY INDEX ROWID| TEST     |  8192 | 49152 |    87     (0)| 00:00:02 |28 |*  2 |   INDEX RANGE SCAN        | IND_TEST |  8192 |       |    28     (0)| 00:00:01 |29 ----------------------------------------------------------------------------------------30 31 Predicate Information (identified by operation id):32 ---------------------------------------------------33 34    2 - access("NAME"='aaaa')35 36 SQL> alter session set optimizer_mode=all_rows;37 38 Session altered.39 40 SQL> select * from test where name='aaaa';41 42 Execution Plan43 ----------------------------------------------------------44 Plan hash value: 135708102045 46 --------------------------------------------------------------------------47 | Id  | Operation      | Name | Rows  | Bytes | Cost (%CPU)| Time     |48 --------------------------------------------------------------------------49 |   0 | SELECT STATEMENT  |     |  8192 | 49152 |    19   (0)| 00:00:01 |50 |*  1 |  TABLE ACCESS FULL| TEST |  8192 | 49152 |    19   (0)| 00:00:01 |51 --------------------------------------------------------------------------52 53 Predicate Information (identified by operation id):54 ---------------------------------------------------55 56    1 - filter("NAME"='aaaa')

  这时我们看到FIRST_ROWS走了索引,就本例而言,这显然不是一种理想的结果,而ALL_ROWS走了全表扫描,我们可以看到成本明显更低。

  参考一下Oracle 10g官方文档关于optimizer_mode参数的描述

OPTIMIZER_MODE

Property Description
Parameter type String
Syntax OPTIMIZER_MODE =

{ first_rows_[1 | 10 | 100 | 1000] | first_rows | all_rows }

Default value all_rows
Modifiable ALTER SESSION, ALTER SYSTEM

OPTIMIZER_MODE establishes the default behavior for choosing an optimization approach for the instance.

Values:

  • first_rows_n

    The optimizer uses a cost-based approach and optimizes with a goal of best response time to return the first n rows (where n = 1, 10, 100, 1000).

  • first_rows

    The optimizer uses a mix of costs and heuristics to find a best plan for fast delivery of the first few rows.

  • all_rows

    The optimizer uses a cost-based approach for all SQL statements in the session and optimizes with a goal of best throughput (minimum resource use to complete the entire statement).

  总结:

  Oracle默认的优化模式并不一定是我们想要的,必须根据自己的系统特定细心的定制。

 

 

 

转载于:https://www.cnblogs.com/Richardzhu/articles/2814599.html

你可能感兴趣的文章
mysql 中if(),left(),right(),with rollup的用法
查看>>
date命令
查看>>
Codeforces205E Little Elephant and Furik and RubikLittle Elephant and Furik and Rubik
查看>>
软件测试的面试
查看>>
1221作业
查看>>
ipython介绍及使用
查看>>
android platform下载地址
查看>>
Skip level 1 on 1
查看>>
【转】常见面试之机器学习算法思想简单梳理
查看>>
OC正则表达式的使用
查看>>
MySQL优化(三):优化数据库对象
查看>>
看到的一个很不错的分析LCA和RMQ的文章(转载,先收着)
查看>>
EXCEL公式及宏
查看>>
组合数学—容斥原理与鸽巢原理
查看>>
中国象棋棋子及棋盘的绘制
查看>>
socketserver剖析.html
查看>>
分享两个网址,一个是使用mssql自带的跟踪工具和分析工具
查看>>
[贪心][高精度][NOIP]国王游戏
查看>>
Java对象创建的过程及对象的内存布局与访问定位
查看>>
设计模式之二-Proxy模式
查看>>