oracle – 如何在PL / SQL中内联变量?

前端之家收集整理的这篇文章主要介绍了oracle – 如何在PL / SQL中内联变量?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
情况

对于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)))
  -- [...]

如您所见,我想限制使用可选范围的组织编号的组织的联合.客户端代码可以调用(假定为快)或不(非常慢)限制的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设计一个一般的执行计划,而内联值将允许分析非常具体的列和索引统计信息.所以我可以想象这不仅仅是巧合.
我错过了什么吗?也许完全有其他的方式来实现查询执行计划的改进,除了变量内联(注意我已经尝试了很多提示,但我不是那个领域的专家)?

在你的一个意见中你说:

“Also I checked varIoUs bind values.
With bind variables I get some FULL
TABLE SCANS,whereas with hard-coded
values,the plan looks a lot better.”

有两条路.如果您为参数传递NULL,那么您正在选择所有记录.在这种情况下,全表扫描是检索数据的最有效方法.如果您传递值,则索引读取可能会更有效率,因为您只选择一小部分信息.

当您使用绑定变量制定查询时,优化器必须做出决定:是否应该假设大部分时间将传递值,否则您将通过null?难.所以看另外一种方法:当你只需要选择一个记录子集,或者当你需要选择所有的记录时,做索引读取,做全表扫描效率会更低吗?

看起来优化器已经全面扫描了全面扫描,因为它是覆盖所有可能性的最低效的操作.

而当您硬编码值时,Optimizer立即知道10 IS NULL评估为FALSE,因此它可以权衡使用索引读取的优点,以找到所需的子集记录.

那么该怎么办?正如你所说的,这个查询只能运行一个月一次,我认为只需要对业务流程进行一些小的更改,以便分开查询:一个用于所有组织,一个用于一个子组织.

“Btw,removing the :R1 IS NULL clause
doesn’t change the execution plan
much,which leaves me with the other
side of the OR condition,:R1 <=
org.no where NULL wouldn’t make sense
anyway,as org.no is NOT NULL”

好的,所以你有一对绑定变量指定一个范围.根据值的分布,不同的范围可能适合不同的执行计划.也就是说,这个范围(可能)适合索引范围扫描…

WHERE org.id BETWEEN 10 AND 11

…而这可能更适合于全表扫描…

WHERE org.id BETWEEN 10 AND 1199999

那就是“变形偷窥”发挥作用的地方.

(当然取决于值的分布).

原文链接:https://www.f2er.com/oracle/204875.html

猜你在找的Oracle相关文章