情况
对于 Oracle 11.2.0.2.0 中大量数据的中型查询,我的查询执行计划遇到了一些问题。为了加快速度,我引入了一个范围过滤器,它大致执行如下操作:
PROCEDURE DO_STUFF(
org_from VARCHAR2 := NULL,
org_to VARCHAR2 := NULL)
-- [...]
JOIN organisations org
ON (cust.org_id = org.id
AND ((org_from IS NULL) OR (org_from <= org.no))
AND ((org_to IS NULL) OR (org_to >= org.no)))
-- [...]
如您所见,我想限制使用可选的组织编号范围JOIN
。organisations
客户端代码可以DO_STUFF
在有(应该很快)或没有(非常慢)限制的情况下调用。
麻烦
问题是,PL/SQL 将为上述org_from
和org_to
参数创建绑定变量,这是我在大多数情况下所期望的:
-- [...]
JOIN organisations org
ON (cust.org_id = org.id
AND ((:B1 IS NULL) OR (:B1 <= org.no))
AND ((:B2 IS NULL) OR (:B2 >= org.no)))
-- [...]
解决方法
只有在这种情况下,当我只内联值时,我测量查询执行计划要好得多,即当 Oracle 执行的查询实际上类似于
-- [...]
JOIN organisations org
ON (cust.org_id = org.id
AND ((10 IS NULL) OR (10 <= org.no))
AND ((20 IS NULL) OR (20 >= org.no)))
-- [...]
“很多”是指快 5-10 倍。请注意,查询很少执行,即每月一次。所以我不需要缓存执行计划。
我的问题
如何在 PL/SQL 中内联值?我知道EXECUTE IMMEDIATE,但我更愿意让 PL/SQL 编译我的查询,而不是进行字符串连接。
我只是测量巧合发生的事情还是我可以假设内联变量确实更好(在这种情况下)?我问的原因是因为我认为绑定变量迫使 Oracle 设计一个通用的执行计划,而内联值将允许分析非常具体的列和索引统计信息。所以我可以想象这不仅仅是巧合。
我错过了什么吗?除了变量内联(注意我也尝试了很多提示,但我不是该领域的专家)之外,也许还有一种完全不同的方法可以实现查询执行计划的改进?