为什么会有常量游标共享

在实际的数据库应用中,我们常常遇到相似的查询逻辑,但实际参数值有所差异的情况。传统的方式是为每个不同参数值编译不同的查询语句,这种重复劳动造成了资源的浪费和性能的下降。为了解决这个问题,Oracle引入了常量游标共享。

原理

当开启了常规游标共享后,Oracle在实际解析目标SQL之前,会先用系统产生的绑定变量(”SYS_B_n”(n=0,1,2……)”)来替换目标SQL的SQL文本中where条件或者values子句(适用于INSERT语句)中的具体输入值,这样替换后实际执行的SQL就已经是使用了绑定变量的改写后的等价SQL,这样就可以做到既有效降低系统硬解析的数量又对应用透明。

解决了什么问题

常量游标共享通过将查询中的实际参数替换为常量值,实现相同查询逻辑的共享。它解决了以下问题:

  1. 减少了重复编译:常量游标共享避免了为每个不同参数值编译新的查询语句,减少了重复编译的开销和数据库的负载。

  2. 提高了内存利用率:共享执行计划的使用减少了存储执行计划所需的内存空间,释放了宝贵的内存资源,从而提升了整体的数据库性能。

  3. 加速了查询速度:重复使用共享的执行计划,减少了缓冲区中存储查询结果的次数,提高了查询速度,增强了系统的响应能力。

如何使用常量游标共享

在Oracle数据库中,可以通过修改系统参数或会话参数的方式来配置常量游标共享。

  1. 修改系统参数:通过修改CURSOR_SHARING参数来启用常量游标共享。可选的参数值如下:

    • EXACT:要求查询中所有参数与常量完全匹配才能共享游标。
    • SIMILAR:只要查询中的实际参数与常量有相似的值(经过转换后),就可以共享游标。
    • FORCE:强制使用常量游标共享,无论实际参数的值如何。
  2. 修改会话参数:可以在会话级别上修改CURSOR_SHARING参数的值,仅对当前会话生效。例如:

1
ALTER SESSION SET CURSOR_SHARING = SIMILAR;

参数说明

  1. EXACT模式:
    Oracle不会用系统产生的绑定变量来替换目标SQL的SQL文本中where条件或者values子句(适用于INSERT语句)中的具体输入值。

  2. SIMILAR模式:
    Oracle会用系统产生的绑定变量来替换目标SQL的SQL文本中where条件或者values子句(适用于INSERT语句)中的具体输入值, 但Oracle只会对那些它认为是安全的谓词条件在替换后重用解析树和执行计划,对于它认为的不安全的谓词条件,即便用系统产生的绑定变量替换后的SQL文本是一模一样的,对于每一个不同的输入值,Oracle都会执行一次硬解析,即此时会出现一个Parent Cursor下挂一堆Child Cursor的现象,而这些Child Cursor中存储的解析树和执行计划很可能是一样的(注意,因为自适应游标共享的引入,这种行为不再适用于Oracle 11g及其后续的版本)。

    所谓“安全的谓词条件”,是指如果一个谓词条件所在的目标SQL的执行计划并不随该谓词条件的输入值的变化而变化,那么该谓词条件就是安全的。与之相反的是,如果目标SQL的执行计划可能会隨着谓词条件的输入值的不同而发生变化,那么该谓词条件就是一个不安全的谓词条件。
    Oracle数据库中典型的不安全的谓词条件有范围查询(使用了>、>=、<、<=、between的谓词条件),使用了帶通配符(%)的LIKE,以及对有直方图统计信息的目标列施加的等值查询等(关于直方图统计信息,会在“第5章Oracle里的统计信息”中详细描述,这里不再赘述)。

  3. FORCE模式:
    不管是“安全的谓词条件”还是“不安全的谓词条件”,当CURSOR_SHARING的值为FORCE时,替换后同一类型的SQL总是会无条件地重用之前硬解析时的解析树和执行计划(注意,因为自适应游标共享的引入,这种行为不再适用于Oracle 11g及其后续的版本)。