Adaptive Cursor Sharing(第三篇)

直方图与ACS

一般情况下ACS必须结合直方图一起使用才能发挥作用,我们看看列上的数据有倾斜,但是却不收集直方图情况下,ACS的表现会怎么样,紧接着还会举出一个特例。以下的代码删除了列status上的直方图。

SQL>begin                                                            

  2     dbms_stats.delete_column_stats(ownname       => 'test',       

  3                                    tabname       => 'test',       

  4                                    colname       => 'status',     

  5                                    col_stat_type => 'HISTOGRAM');

  6   end;                                                            

  7   /                                                               

 

PL/SQL procedure successfully completed.

 

SQL>alter system flush shared_pool;

 

System altered.

删除直方图是11G提供的功能,如果你的版本小于11G,可以重新收集表的统计信息不收集直方图。

SQL>exec :a :='Active'

PL/SQL procedure successfully completed.

SQL>select /*+ find_me */ count(name) from test where status=:a;

COUNT(NAME)

-----------

      49900

SQL>exec :a:='Inactive'

 

PL/SQL procedure successfully completed.

 

SQL>select /*+ find_me */ count(name) from test where status=:a;

 

COUNT(NAME)

-----------

        100

 

SQL>-- 直方图

SQL>SELECT   hash_value, sql_id, child_number, bucket_id, COUNT

  2       FROM v$sql_cs_histogram

  3      WHERE sql_id='a9cf9a1ky3bda'

  4   ORDER BY sql_id, child_number;

 

HASH_VALUE SQL_ID          CHILD_NUMBER  BUCKET_ID      COUNT

---------- --------------- ------------ ---------- ----------

1709288874 a9cf9a1ky3bda              0          1          1

1709288874 a9cf9a1ky3bda              0          0          1

1709288874 a9cf9a1ky3bda              0          2          0

 

SQL>select * from table(dbms_xplan.display_cursor('a9cf9a1ky3bda',null));

 

PLAN_TABLE_OUTPUT

-------------------------------------------------------------------------------

SQL_ID  a9cf9a1ky3bda, child number 0

-------------------------------------

select /*+ find_me */ count(name) from test where status=:a

 

Plan hash value: 1950795681

 

---------------------------------------------------------------------------

| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |

---------------------------------------------------------------------------

|   0 | SELECT STATEMENT   |      |       |       |    51 (100)|          |

|   1 |  SORT AGGREGATE    |      |     1 |    25 |            |          |

|*  2 |   TABLE ACCESS FULL| TEST | 25000 |   610K|    51   (2)| 00:00:01 |

---------------------------------------------------------------------------

 

Predicate Information (identified by operation id):

---------------------------------------------------

 

   2 - filter("STATUS"=:A)

 

 

我们看到v$sql_cs_histogram里的这个cursor的3个桶里已经有2个桶的count非0,说明优化器已经认识到第二次执行返回的记录数跟第一次大大不同了。按照我们之前所做的测试,如果列上有直方图,再次执行这个SQL,应该就会新产生一个游标了。我们来看看缺少直方图会怎么样:

SQL> select /*+ find_me */ count(name) from test where status=:a;

 

 

COUNT(NAME)

-----------

        100

 

SQL> -- 检查ACS状态

SQL>SELECT child_number, executions, buffer_gets, is_bind_sensitive,

  2          is_bind_aware

  3     FROM v$sql

  4    WHERE sql_id='a9cf9a1ky3bda';

 

CHILD_NUMBER EXECUTIONS BUFFER_GETS IS IS

------------ ---------- ----------- -- --

           0          2         463 Y  N

           1          1         210 Y  Y

 

SQL>

SQL>-- 直方图

SQL>SELECT   hash_value, sql_id, child_number, bucket_id, COUNT

  2       FROM v$sql_cs_histogram

  3      WHERE sql_id='a9cf9a1ky3bda'

  4   ORDER BY sql_id, child_number;

 

HASH_VALUE SQL_ID          CHILD_NUMBER  BUCKET_ID      COUNT

---------- --------------- ------------ ---------- ----------

1709288874 a9cf9a1ky3bda              0          1          1

1709288874 a9cf9a1ky3bda              0          0          1

1709288874 a9cf9a1ky3bda              0          2          0

1709288874 a9cf9a1ky3bda              1          1          0

1709288874 a9cf9a1ky3bda              1          0          1

1709288874 a9cf9a1ky3bda              1          2          0

 

6 rows selected.

 

SQL>

SQL>-- 统计信息

SQL>SELECT hash_value, sql_id, child_number,  executions,

  2           rows_processed

  3      FROM v$sql_cs_statistics

  4     WHERE sql_id='a9cf9a1ky3bda'

  5  ORDER BY sql_id, child_number;

 

HASH_VALUE SQL_ID          CHILD_NUMBER EXECUTIONS ROWS_PROCESSED

---------- --------------- ------------ ---------- --------------

1709288874 a9cf9a1ky3bda              0          1            101

1709288874 a9cf9a1ky3bda              1          1          49901

 

SQL>

SQL>-- 选择率

SQL>SELECT   hash_value, sql_id, child_number, predicate, range_id, low, high

  2      FROM v$sql_cs_selectivity

  3     WHERE sql_id='a9cf9a1ky3bda'

  4  ORDER BY sql_id, child_number;

 

HASH_VALUE SQL_ID          CHILD_NUMBER PREDICATE    RANGE_ID LOW        HIGH

---------- --------------- ------------ ---------- ---------- ---------- ----------

1709288874 a9cf9a1ky3bda              1 =A                  0 0.450000   0.550000

SQL>select * from table(dbms_xplan.display_cursor('a9cf9a1ky3bda',null));

 

PLAN_TABLE_OUTPUT

-------------------------------------------------------------------------------

SQL_ID  a9cf9a1ky3bda, child number 0

-------------------------------------

select /*+ find_me */ count(name) from test where status=:a

 

Plan hash value: 1950795681

 

---------------------------------------------------------------------------

| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |

---------------------------------------------------------------------------

|   0 | SELECT STATEMENT   |      |       |       |    51 (100)|          |

|   1 |  SORT AGGREGATE    |      |     1 |    25 |            |          |

|*  2 |   TABLE ACCESS FULL| TEST | 25000 |   610K|    51   (2)| 00:00:01 |

---------------------------------------------------------------------------

 

Predicate Information (identified by operation id):

---------------------------------------------------

 

   2 - filter("STATUS"=:A)

 

SQL_ID  a9cf9a1ky3bda, child number 1

-------------------------------------

select /*+ find_me */ count(name) from test where status=:a

 

Plan hash value: 1950795681

 

---------------------------------------------------------------------------

| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |

---------------------------------------------------------------------------

|   0 | SELECT STATEMENT   |      |       |       |    51 (100)|          |

|   1 |  SORT AGGREGATE    |      |     1 |    25 |            |          |

|*  2 |   TABLE ACCESS FULL| TEST | 25000 |   610K|    51   (2)| 00:00:01 |

---------------------------------------------------------------------------

 

Predicate Information (identified by operation id):

---------------------------------------------------

 

   2 - filter("STATUS"=:A)

我们看到虽然新生成了一个子cursor,而且这个cursor的bind aware为Y,但是查看执行计划,发现新生成的child_number为1的执行计划也为全表扫描,而非索引扫描。其实优化器在发现这个cursor处理的行数发生巨变后,下次再次执行的话,就会窥探变量值,然后根据窥探到的值进行硬解析,但是由于不存在直方图,优化器认为索引扫描的代价太高,因此硬解析后依然还是生成了全表扫描的执行计划。我们看看索引扫描的COST值是多少:

SQL>select /*+ index(test) */ count(name) from test where status=:a;

 

COUNT(NAME)

-----------

        100

 

SQL>select * from table(dbms_xplan.display_cursor);

 

PLAN_TABLE_OUTPUT

-------------------------------------------------------------------------------

SQL_ID  88jwg2t11b237, child number 0

-------------------------------------

select /*+ index(test) */ count(name) from test where status=:a

 

Plan hash value: 2948918962

 

--------------------------------------------------------------------------------------------

| Id  | Operation                    | Name        | Rows  | Bytes | Cost (%CPU)| Time     |

--------------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT             |             |       |       |   218 (100)|          |

|   1 |  SORT AGGREGATE              |             |     1 |    25 |            |          |

|   2 |   TABLE ACCESS BY INDEX ROWID| TEST        | 25000 |   610K|   218   (1)| 00:00:03 |

|*  3 |    INDEX RANGE SCAN          | TEST_ID_IND | 25000 |       |    63   (0)| 00:00:01 |

--------------------------------------------------------------------------------------------

 

Predicate Information (identified by operation id):

---------------------------------------------------

 

   3 - access("STATUS"=:A)

 

索引扫描的cost 为218已经超过了全表扫描的cost 51,因此由于缺少直方图即使重新硬解析也只能产生全表扫描的执行计划。优化器在尝试纠正错误,但是无耐给的信息不够,错误不能得到有效的纠正。

但是有特例,如果列上做的是非等值查询,即使没有直方图,依然可能会使用到ACS,我们看一个案例:

l 创建一张表,500万的记录数,id字段根据rownum生成

l 在id字段上创建索引

l 收集统计信息,不收集直方图

l 清空shared_pool


SQL>create table t as select rownum id,a.* from dba_objects a ,dba_objects b where rownum<5000001;

 

Table created.

 

SQL>create index i on t(id);

 

Index created.

 

SQL>begin

  2    dbms_stats.gather_table_stats(ownname          => 'test',

  3                                  tabname          => 't',

  4                                  no_invalidate    => FALSE,

  5                                  estimate_percent => 100,

  6                                  force            => true,

  7                                  degree           => 5,

  8                              method_opt       => 'for  all  columns size 1',

  9                                  cascade          => true);

 10  end;

 11  /

 

PL/SQL procedure successfully completed.

SQL>alter system flush shared_pool;

 

System altered.

 

SQL>var a number;

SQL>exec :a :=4999999;

 

PL/SQL procedure successfully completed.

 

SQL>select count(object_id) from t where id > :a;

 

COUNT(OBJECT_ID)

----------------

               1

 

SQL>select * from table(dbms_xplan.display_cursor);

 

PLAN_TABLE_OUTPUT

-------------------------------------------------------------------------------

SQL_ID  1vmttxn3jrww3, child number 0

-------------------------------------

select count(object_id) from t where id > :a

 

Plan hash value: 3694077449

 

-------------------------------------------------------------------------------------

| Id  | Operation                    | Name | Rows  | Bytes | Cost (%CPU)| Time     |

-------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT             |      |       |       |     4 (100)|          |

|   1 |  SORT AGGREGATE              |      |     1 |    10 |            |          |

|   2 |   TABLE ACCESS BY INDEX ROWID| T    |     1 |    10 |     4   (0)| 00:00:01 |

|*  3 |    INDEX RANGE SCAN          | I    |     1 |       |     3   (0)| 00:00:01 |

-------------------------------------------------------------------------------------

 

Predicate Information (identified by operation id):

---------------------------------------------------

 

   3 - access("ID">:A)

 

先查询了id大于4999999的,由于只返回一条记录,记录集非常小,ORACLE选择了索引扫描。我们看看ACS相关视图的表现:

SQL> -- 检查ACS状态

SQL>SELECT child_number, executions, buffer_gets, is_bind_sensitive,

  2          is_bind_aware

  3     FROM v$sql

  4    WHERE sql_id='1vmttxn3jrww3';

 

CHILD_NUMBER EXECUTIONS BUFFER_GETS IS IS

------------ ---------- ----------- -- --

           0          1          48 Y  N

 

SQL>

SQL>-- 直方图

SQL>SELECT   hash_value, sql_id, child_number, bucket_id, COUNT

  2       FROM v$sql_cs_histogram

  3      WHERE sql_id='1vmttxn3jrww3'

  4   ORDER BY sql_id, child_number;

 

HASH_VALUE SQL_ID          CHILD_NUMBER  BUCKET_ID      COUNT

---------- --------------- ------------ ---------- ----------

 119272323 1vmttxn3jrww3              0          0          1

 119272323 1vmttxn3jrww3              0          2          0

 119272323 1vmttxn3jrww3              0          1          0

 

由于处理的结果集较小,执行的统计被列入到了bucket 0。我们继续看看查询id>1的情况下,这个时候要几乎返回整个表的数据:

SQL>exec :a :=1;

select count(object_id) from t where id > :a;

 

PL/SQL procedure successfully completed.

 

SQL>

 

COUNT(OBJECT_ID)

----------------

         4999999

   
SQL> -- 检查ACS状态

SQL>SELECT child_number, executions, buffer_gets, is_bind_sensitive,

  2          is_bind_aware

  3     FROM v$sql

  4    WHERE sql_id='1vmttxn3jrww3';

 

CHILD_NUMBER EXECUTIONS BUFFER_GETS IS IS

------------ ---------- ----------- -- --

           0          2       76425 Y  N

 

SQL>

SQL>-- 直方图

SQL>SELECT   hash_value, sql_id, child_number, bucket_id, COUNT

  2       FROM v$sql_cs_histogram

  3      WHERE sql_id='1vmttxn3jrww3'

  4   ORDER BY sql_id, child_number;

 

HASH_VALUE SQL_ID          CHILD_NUMBER  BUCKET_ID      COUNT

---------- --------------- ------------ ---------- ----------

 119272323 1vmttxn3jrww3              0          0          1

 119272323 1vmttxn3jrww3              0          2          1

 119272323 1vmttxn3jrww3              0          1          0

v$sql_cs_histogram已经捕获到本次执行的SQL处理的结果集已经跟第一次执行大大不同,执行的统计已经被列入到了bucket_id为2的桶上。再次执行:

SQL>select count(object_id) from t where id > :a;

COUNT(OBJECT_ID)

----------------

         4999999

 

SQL>select * from table(dbms_xplan.display_cursor);

 

PLAN_TABLE_OUTPUT

-------------------------------------------------------------------------------

SQL_ID  1vmttxn3jrww3, child number 1

-------------------------------------

select count(object_id) from t where id > :a

 

Plan hash value: 2966233522

 

---------------------------------------------------------------------------

| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |

---------------------------------------------------------------------------

|   0 | SELECT STATEMENT   |      |       |       | 14373 (100)|          |

|   1 |  SORT AGGREGATE    |      |     1 |    10 |            |          |

|*  2 |   TABLE ACCESS FULL| T    |  4999K|    47M| 14373   (2)| 00:02:53 |

---------------------------------------------------------------------------

 

Predicate Information (identified by operation id):

---------------------------------------------------

 

   2 - filter("ID">:A)

 

再次执行后,已经产生出了全表扫描的执行计划了,因为再次执行,优化器会去窥探绑定变量的值做硬解析,优化器重新评估索引扫描和全表扫描的cost后选择了全表扫描,下面的代码给出了ACS相关视图的变化和索引扫描的cost。


SQL> -- 检查ACS状态

SQL>SELECT child_number, executions, buffer_gets, is_bind_sensitive,

  2          is_bind_aware

  3     FROM v$sql

  4    WHERE sql_id='1vmttxn3jrww3';

 

CHILD_NUMBER EXECUTIONS BUFFER_GETS IS IS

------------ ---------- ----------- -- --

           0          2       76425 Y  N

           1          1       64685 Y  Y

SQL>-- 直方图

SQL>SELECT   hash_value, sql_id, child_number, bucket_id, COUNT

  2       FROM v$sql_cs_histogram

  3      WHERE sql_id='1vmttxn3jrww3'

  4   ORDER BY sql_id, child_number;

 

HASH_VALUE SQL_ID          CHILD_NUMBER  BUCKET_ID      COUNT

---------- --------------- ------------ ---------- ----------

 119272323 1vmttxn3jrww3              0          1          0

 119272323 1vmttxn3jrww3              0          0          1

 119272323 1vmttxn3jrww3              0          2          1

 119272323 1vmttxn3jrww3              1          1          0

 119272323 1vmttxn3jrww3              1          0          0

 119272323 1vmttxn3jrww3              1          2          1

 

SQL>select /*+ index(t) */count(object_id) from t where id > :a;

select

COUNT(OBJECT_ID)

----------------

         4999999

 

SQL>select * from table(dbms_xplan.display_cursor);

 

PLAN_TABLE_OUTPUT

--------------------------------------------------------------------------------------------

SQL_ID  51qy01unwm5r0, child number 0

-------------------------------------

select /*+ index(t) */count(object_id) from t where id > :a

 

Plan hash value: 3694077449

 

-------------------------------------------------------------------------------------

| Id  | Operation                    | Name | Rows  | Bytes | Cost (%CPU)| Time     |

-------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT             |      |       |       | 76652 (100)|          |

|   1 |  SORT AGGREGATE              |      |     1 |    10 |            |          |

|   2 |   TABLE ACCESS BY INDEX ROWID| T    |  4999K|    47M| 76652   (1)| 00:15:20 |

|*  3 |    INDEX RANGE SCAN          | I    |  4999K|       | 11792   (1)| 00:02:22 |

-------------------------------------------------------------------------------------

 

Predicate Information (identified by operation id):

---------------------------------------------------

 

   3 - access("ID">:A)

 

 

v$sql中也已经出现了child_number为1的子游标。 is_bind_sensitive和is_bind_aware都为Y。v$sql_cs_histogram中也产生出了新的3行记录。说明ACS已经发挥作用产生了新的游标,而且执行计划也非常优秀。上面没有直方图的第一个做等值查询的例子,虽然ACS也发挥了作用,但是由于缺少直方图,并没有产生出优秀的执行计划。

从上面的两个例子可以看出,所谓ACS发挥作用,只不过是给优化器一个机会,让其根据具体的绑定变量的值重新硬解析,但是至于硬解析出来的执行计划优不优秀,要看统计信息的完整度、准确度以及你查询的谓词是做的何种查询。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/22034023/viewspace-2153621/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/22034023/viewspace-2153621/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于preevision的autosar adaptive设计-上篇 autosar adaptive是一种汽车电子系统的架构和开发标准,旨在满足汽车行业对日益增长的功能和复杂性的需求。而基于preevision的autosar adaptive设计是一种通过使用preevision工具进行autosar adaptive系统设计和开发的方法。 preevision是一种功能强大的工程工具,专门用于汽车电子系统的设计和开发。它提供了一套丰富的工具和功能,可帮助工程师轻松地创建、模拟和验证autosar adaptive系统的设计。 基于preevision的autosar adaptive设计包括以下关键步骤: 首先,工程师需要使用preevision工具创建autosar adaptive系统的模型。这可以通过使用preevision的图形界面来完成,工程师可以在其中定义autosar adaptive系统的各个组件,包括应用程序、服务、接口和通信。 接下来,工程师需要使用preevision工具进行模型的验证和仿真。通过使用preevision的仿真功能,工程师可以模拟autosar adaptive系统的行为和性能,以确保系统的设计满足要求。 一旦模型被验证和仿真成功,工程师就可以使用preevision工具生成与autosar adaptive系统相关的代码和文档。preevision提供了自动代码生成的功能,可以根据系统模型生成各个组件的代码,包括应用程序、服务和接口。 最后,工程师可以使用preevision工具进行系统的集成和部署。preevision提供了一套完整的工具和功能,可以帮助工程师将autosar adaptive系统部署到实际的汽车电子控制单元(ECU)上,并与其他系统进行集成。 基于preevision的autosar adaptive设计具有许多优点。首先,它可以帮助工程师快速而准确地设计和开发autosar adaptive系统,提高开发效率。其次,preevision提供了一套丰富的工具和功能,使工程师能够对系统进行全面的验证和仿真,从而确保系统的质量和性能。最后,基于preevision的autosar adaptive设计能够帮助企业实现系统的自动化开发和部署,减少人力成本和时间成本。 综上所述,基于preevision的autosar adaptive设计是一种高效、准确和可靠的方法,可以帮助汽车行业设计和开发符合autosar adaptive标准的系统。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值