
1.3 如何确定正在发生智能扫描
通过前面的学习可知,全扫描、直接路径读取、Exadata存储是智能扫描的三大先决条件,但它们不是充分条件,也即满足了这三大条件也并不代表智能扫描一定会发生。那么又该如何判断智能扫描是否已经发生?
1.3.1 执行计划中出现全扫描并不代表已经智能扫描
正如以上标题所表明的,虽然在SQL语句的执行计划中出现了STORAGE FULL等字样,但这并不代表该SQL语句已经进行了智能扫描操作。
下面通过示例来验证,即使执行计划中出现了全扫描也并不代表已经智能扫描,见代码清单1.15。
代码清单1.15 验证即使执行计划中出现了全扫描也并不代表已经智能扫描(1)

查询test.hello这张表的数据,从执行计划可以看出是TABLE ACCESS STORAGE FULL;再查询另外一张表test.test的数据,从执行计划可以看出同样也是T ABLE ACCESS STORAGE FULL。
下面获取刚执行的这两条语句的SQL_ID,并从v$sql性能视图中查询某条具体的SQL语句是否有IO的数据卸载操作。
代码清单1.15 验证即使执行计划中出现了全扫描也并不代表已经智能扫描(2)

从以上的示例可以看出,执行计划中出现STORAGE FULL关键字,仅仅表示该SQL语句符合智能扫描的条件之一,即进行了full table scans或fast full index scans操作,但这并不意味着SQL语句已经进行了智能扫描,而真正想智能扫描,则还必须进行数据的直接路径读取。
数据库参数cell_offload_plan_display决定了执行计划中是否显示storage关键字。该参数有3个参数值,见表1.1。
表1.1 cell_offload_plan_display参数说明

1.3.2 如何确认智能扫描已经工作
既然无法从执行计划层面看出哪些SQL语句已经进行了智能扫描操作,那么有哪些方法可以判断具体的某条SQL语句是否有智能扫描呢?有以下几种常见的方法:10046事件、数据库性能视图。
1.10046事件
10046事件是Oracle数据库中任何SQL语句最真实的运行记录,它会详细记录SQL语句运行过程中的等待和花费。通过设置这个事件可以得到Oracle内部执行系统解析、调用、等待、绑定变量等详细的跟踪信息,对于分析系统的性能有着非常重要的作用。
同样,通过10046事件可以捕获到某条SQL语句是否进行了智能扫描操作。下面通过示例进行说明。在运行某条SQL语句之前,先对该会话设置10046事件,见代码清单1.16。
代码清单1.16 10046事件验证是否发生智能扫描(1)

获取该SQL语句的10046事件所生成的跟踪文件名为exadb1_ora_58674.trc。下面分析该10046事件生成的trace文件,其部分内容如下。
代码清单1.16 10046事件验证是否发生智能扫描(2)

将10046事件所生成的跟踪文件使用tkprof工具格式化后的信息如下。
代码清单1.16 10046事件验证是否发生智能扫描(3)

从该10046事件生成的跟踪文件的内容可以看出,该SQL语句的大量等待事件为cell smart table scan。出现这个等待事件,则表明该SQL语句进行了智能扫描。除了cell smart table scan,如果某条SQL语句出现了cell smart index scan等待事件,则表明该SQL语句也进行了智能扫描。
2.v$sql视图
如果是一条已经运行过的SQL语句,或某些SQL语句不允许通过“再次执行”来重现,就无法再使用10046事件来分析该SQL语句是否已经智能扫描。在这种情况下,可以通过数据库性能视图,如v$sql、V$SQLAREA、V$SQLSTATS、V$SQLAREA_PLAN_HASH、V$SQLSTATS_PLAN_HASH等来定位某条SQL语句。
在这些数据库性能视图中,主要字段说明如表1.2所示。
表1.2 与v$sql相关的数据库性能视图主要字段说明

在前面的章节中,其实已经大量使用该类性能视图来检测SQL语句是否使用了智能扫描,这里就不再重复了。有一点需要提醒的是,在很多不同的资料中,计算智能扫描的IO节省比率的公式有两种。
■ 公式1:智能扫描IO节省比率=(IO_CELL_OFFLOAD_ELIGIBLE_BYTES-IO_INTERCONNECT_BYTES)/IO_CELL_OFFLOAD_ELIGIBLE_BYTES∗100%。
■ 公式2:智能扫描IO节省比率=(IO_CELL_OFFLOAD_ELIGIBLE_BYTES-IO_CELL_OFFLOAD_RETURNED_BYTES)/IO_CELL_OFFLOAD_ELIGIBLE_BYTES∗100%。
这两个计算公式其实都没有什么问题,因为当发生智能扫描时,IO_INTERCONNECT_BYTES字段的值与IO_CELL_OFFLOAD_RETURNED_BYTES字段的值基本相当,而IO_INTERCONNECT_BYTES字段的值会比IO_CELL_OFFLOAD_RETURNED_BYTES字段的值稍稍高一些。
3.v$mystat视图
除了与v$sql相关的数据库性能视图外,还可以通过v$mystat、v$sesstat或v$sysstat性能视图来判断某条SQL语句是否进行了智能扫描。如表1.3所示为v$mystat视图中涉及智能扫描的主要字段说明。
表1.3 v$mystat性能视图主要字段说明

下面以v$mystat性能视图为例,来学习如何利用该性能视图判断SQL语句是否已经智能扫描,见代码清单1.17。
代码清单1.17 v$mystat性能视图验证是否发生智能扫描

从以上代码输出可以看出,当第一次查询v$mystat性能视图时,与智能扫描相关的性能指标全部为0;当执行完SQL语句之后,再次查询v$mystat性能视图时,与智能扫描相关的性能指标都发生了变化。这说明刚刚执行的SQL语句已经智能扫描。如果执行完SQL语句之后,与智能扫描相关的性能指标没有任何变化,则说明刚刚执行的SQL语句没有发生智能扫描操作。
4.SQL Monitor工具
在Oracle 11g数据库中有一个新特性——SQL Monitor,可用来查看某一条运行的SQL语句是否使用了智能扫描。
使用方法非常简单,可以使用命令行来生成HTML格式的SQL Monitor报告,生成的方式见代码清单1.18。
代码清单1.18 生成HTML格式的SQL Monitor报告

只需将上述代码清单中的SQL_ID修改为具体SQL语句所对应的SQL_ID,即可获取该SQL语句的SQL Monitor报告。
如果SQL语句运行的时间太短,则SQL Monitor特性是不会对其进行监控的。如要针对这种SQL语句进行监控,则需要手动对SQL语句加上/∗+monitor∗/hint。获取到的HTML报告如图1.7所示。

图1.7 SQL Monitor报告
从SQL Monitor报告中可以看出,如果该SQL语句进行了智能扫描,则Cell Offload Efficiency列会计算出该SQL语句节省的IO百分比。
注意:目前,优化器还不能计算出智能扫描花费的成本,所以是否进行智能扫描并不是在SQL语句分析阶段生成执行计划时决定的,而是一个实时的决策过程。它主要依据以下规则:①首先优化器选择使用全表扫描或索引快速全扫描,此时不会考虑当前环境是否为Exadata环境;②接着依据表的大小、脏数据块的多少、已经缓存的数据块多少、与_small_table_threshold和_serial_direct_read等相关的隐含参数来决定是否进行直接路径读取,该算法与非Exadata环境完全一样;③如果数据存储在Exadata环境,同时cell_offload_processing参数为默认值,未进行修改,则选择使用智能扫描。