今天有朋友遇到了一个SQL问题,最终检查到SQL存在两个子指针,错误的执行计划选择了MERGE JOIN CARTESIAN,在检查SQL为何不能共享时,查询V$SQL_SHARED_CURSOR视图:

SELECT * FROM V$SQL_SHARED_CURSOR WHERE sql_id = '4svx3gu1gvx8n'

发现不能共享的原因是ROLL_INVALID_MISMATCH。


那么这个ROLL_INVALID_MISMATCH是什么含义呢?

Oracle的文档这样注释:Marked for rolling invalidation and invalidation window exceeded


这是什么意思呢?在Oracle收集对象统计信息的时候,是否INVALID相关Cursor是一个可选问题,在DBMS_STATS包的调用过程中,这个选择是可以设置的,缺省的有一些常量指标,如下:


DBMS_STATS Constants


Name Type Value Description

AUTO_CASCADE

BOOLEAN

NULL

Lets Oracle decide whether to collect statistics for indexes or not


AUTO_DEGREE

NUMBER

32768

Lets Oracle select the degree of parallelism based on size of the object, number of CPUs and initialization parameters


AUTO_INVALIDATE

BOOLEAN

NULL

Lets Oracle decide when to invalidate dependent cursors


AUTO_SAMPLE_SIZE

NUMBER

0

Indicates that auto-sample size algorithms should be used


在分析对象时,比如分析表时,no_invalidate 就于此有关:


DBMS_STATS.GATHER_TABLE_STATS (

ownname VARCHAR2,

tabname VARCHAR2,

partname VARCHAR2 DEFAULT NULL,

estimate_percent NUMBER DEFAULT to_estimate_percent_type

(get_param('ESTIMATE_PERCENT')),

block_sample BOOLEAN DEFAULT FALSE,

method_opt VARCHAR2 DEFAULT get_param('METHOD_OPT'),

degree NUMBER DEFAULT to_degree_type(get_param('DEGREE')),

granularity VARCHAR2 DEFAULT GET_PARAM('GRANULARITY'),

cascade BOOLEAN DEFAULT to_cascade_type(get_param('CASCADE')),

stattab VARCHAR2 DEFAULT NULL,

statid VARCHAR2 DEFAULT NULL,

statown VARCHAR2 DEFAULT NULL,

no_invalidate BOOLEAN DEFAULT to_no_invalidate_type (

get_param('NO_INVALIDATE')),

force BOOLEAN DEFAULT FALSE);


在10g中,缺省的使用AUTO_INVALIDATE选项时,分析对象之后,原有SQL并不会立即失效,失效时间和SQL执行有关,同时受到另外一个参数的影响:_optimizer_invalidation_period ,这个参数的缺省值是18000s(以下是Oracle 10gR2的缺省设置),当超过这个时间,SQL会重新硬解析,生成一个新的SQL,并标记与之前Cursor不能共享的原因为ROLL_INVALID_MISMATCH :


SQL> SELECT x.ksppinm NAME, y.ksppstvl VALUE, x.ksppdesc describ

 2    FROM SYS.x$ksppi x, SYS.x$ksppcv y

 3   WHERE x.indx = y.indx AND x.ksppinm LIKE '%&par%'

 4  /

Enter value for par: optimizer_invalidation_period

old   3:  WHERE x.indx = y.indx AND x.ksppinm LIKE '%&par%'

new   3:  WHERE x.indx = y.indx AND x.ksppinm LIKE '%optimizer_invalidation_period%'


NAME                           VALUE                DESCRIB

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

_optimizer_invalidation_period 18000                time window for invalidation of cursors of analyzed objects


这一设置的作用是为了减少统计信息收集带来的大量SQL重解析带来的性能冲击。


ROLL_INVALID_MISMATCH 说的就是这样一件事。


-The End-