在 Oracle 数据库中,
CURSOR_SHARING
参数和
FORCE_MATCHING_SIGNATURE
是用于优化 SQL 语句共享和执行计划稳定性的工具。然而,它们在某些情况下存在局限性,尤其是在处理复杂或动态生成的 SQL 语句时。本文将探讨这些局限性,并分析它们对 SQL 计划稳定性的影响。
CURSOR_SHARING=FORCE 的作用
CURSOR_SHARING=FORCE
是 Oracle 提供的一个参数,用于强制共享具有相似文本但字面值不同的 SQL 语句。它的主要目的是减少硬解析的次数,从而提高数据库的性能。
此外,相同的机制(在计算 SQL 哈希值以进行库缓存查找之前,将字面值替换为绑定变量占位符)也可以用于强制为仅字面值不同的 SQL 语句应用 SQL 配置文件。只需使用
DBMS_SQLTUNE.ACCEPT_PROFILE(…, FORCE_MATCH=>TRUE) 接受 SQL 配置文件即可。
然而,这种“强制匹配”有一个局限性,可能会使其在应用程序使用动态生成 SQL 的数据库中几乎无法实现计划稳定性。
如下面的示例:当cursor_sharing=EXACT默认值的情况下, SQL 语句不能被共享,要进行硬解析。
show parameter cursor_sharing
set linesize 10000
col SQL_TEXT for a100
col force_matching_signature for 999999999999999999999999999
SELECT * FROM dual WHERE rownum IN (1,2,3);
SELECT * FROM dual WHERE rownum IN (4,5,6);
SELECT sql_id,hash_value,force_matching_signature,sql_text FROM v$sql WHERE sql_text like '%SELECT * FROM dual%'order by sql_text;
SELECT sql_id,hash_value,force_matching_signature,sql_text FROM v$sql WHERE sql_id = (SELECT prev_sql_id FROM v$session WHERE sid = USERENV('SID'));
我们看到SELECT * FROM dual WHERE rownum IN (1,2,3);和SELECT * FROM dual WHERE rownum IN (4,5,6);的sql文本不能被共享, HASH_VALUE的值是不同的,但是FORCE_MATCHING_SIGNATURE的值是相同的。

在
CURSOR_SHARING=FORCE
的情况下,Oracle 会将它们视为相同的 SQL 语句,并使用相同的执行计划。
用于强制共享具有相似文本但字面值不同的 SQL 语句。它的主要目的是减少硬解析的次数,从而提高数据库的性能。
ALTER SESSION SET cursor_sharing = FORCE; set linesize 10000 col SQL_TEXT for a100 col force_matching_signature for 999999999999999999999999999 SELECT * FROM dual WHERE rownum IN (1,2,3); SELECT * FROM dual WHERE rownum IN (4,5,6); SELECT sql_id,hash_value,force_matching_signature,sql_text FROM v$sql WHERE sql_text like '%SELECT * FROM dual%' order by sql_text;

我们看到字面值
1,2,3和4,5,6
被替换为 SQL 文本中的
:SYS_B_x
绑定变量。SQL 哈希值(以及
SQL_ID
和
force_matching_signature
)是在此替换完成后计算的。因此两条sql的hash_value和forec_mathing_signature值是相同的。
CURSOR_SHARING=FORCE 的局限性
尽管
CURSOR_SHARING=FORCE 在某些场景下非常有用,但它也存在一些局限性:
-
不适合所有 SQL 语句:对于某些复杂的 SQL 语句,尤其是包含动态 SQL 或复杂表达式的语句,
CURSOR_SHARING=FORCE 可能会导致性能下降或执行计划不稳定。 -
无法解决所有硬解析问题:虽然
CURSOR_SHARING=FORCE 可以减少硬解析的次数,但它并不能完全消除硬解析。在某些情况下,仍然需要手动优化 SQL 语句或使用其他技术(如 SQL 计划基线)来确保执行计划的稳定性。FORCE_MATCHING_SIGNATURE 的作用
FORCE_MATCHING_SIGNATURE 是 Oracle 提供的一个功能,用于识别具有相同结构但字面值不同的 SQL 语句。它通过计算 SQL 语句的签名来实现这一点,从而帮助数据库管理员 识别潜在的 SQL 共享问题。FORCE_MATCHING_SIGNATURE 的局限性
尽管
FORCE_MATCHING_SIGNATURE 可以帮助识别相似的 SQL 语句,但它也存在一些局限性:无法自动优化执行计划:
FORCE_MATCHING_SIGNATURE 只能帮助识别相似的 SQL 语句,但它并不能自动优化这些语句的执行计划。数据库管理员仍然需要手动干预,以确保执行计划的稳定性。 -
签名计算的复杂性:在某些情况下,SQL 语句的签名可能会因为微小的变化而不同,这可能导致
FORCE_MATCHING_SIGNATURE 无法正确识别相似的 SQL 语句。 -
无法解决所有 SQL 共享问题:与
CURSOR_SHARING=FORCE 类似,FORCE_MATCHING_SIGNATURE 也无法解决所有 SQL 共享问题。特别是在处理动态 SQL 或复杂查询时,可能需要其他技术来确保执行计划的稳定性。总结
CURSOR_SHARING=FORCE 和FORCE_MATCHING_SIGNATURE 是 Oracle 数据库中用于优化 SQL 共享和执行计划稳定性的重要工具。然而,它们在某些情况下存在局限性,尤其是在处理复杂或动态生成的 SQL 语句时。为了确保 SQL 执行计划的稳定性,数据库管理员可能需要结合其他技术(如 SQL 计划基线、SQL 配置文件等)来进行综合优化。
执行计划可能不最优:由于 Oracle 会将不同的字面值替换为绑定变量,这可能导致执行计划无法针对特定的字面值进行优化。例如,某些查询可能在小范围内扫描时效率更高,但在大范围内扫描时效率较低。如果使用绑定变量,优化器无法根据实际值选择最佳计划。
