通过使用变量作为参数,选择查询花费了太多时间

时间:2019-07-19 14:06:58

标签: sql oracle oracle-apps

当我在以下条件下通过硬编码在查询下运行时,它可以快速运行:

... AND ooha.order_number BETWEEN NVL(5339914,ooha.order_number) 
    AND NVL(5339914,ooha.order_number)

但是当我将其作为参数使用时,它花费了将近2个小时以上的太多时间

... AND ooha.order_number BETWEEN NVL(:p,ooha.order_number) 
    AND NVL(:q,ooha.order_number)

以下是我的原始代码,请按照开发人员的观点尝试所有可能的解决方案:

SELECT ooha.order_number,
    hps.addressee cus_name,
    oola.line_number,
    (SELECT rtrim(extract(xmlagg(xmlelement("a",set_name                        -- query to check ship_set
      ||'/')),'//text()'),',')
    FROM oe_sets
    WHERE header_id = ooha.header_id
    AND set_type    = 'SHIP_SET'
    ) ship_set,
  msib.segment1 item_name,
  ooha.booked_date,
  oola.schedule_ship_date,
  mp.ORGANIZATION_CODE,
  oola.ordered_quantity,
  oola.subinventory,
  oola.project_id,
  (SELECT description FROM fnd_user WHERE user_id = ooha.attribute12            -- query to check Customer Delivery Partner  
  ) cdp,
  (SELECT NVL(SUM(reservation_quantity),0)                                      -- query to check Reservation Quantity
  FROM mtl_reservations
  WHERE demand_source_line_id = oola.line_id
  ) reserved_qty,
  oola.header_id,
  oola.line_id,
  msib.inventory_item_id,
  msib.organization_id,
  msib.item_type,
  msib.inventory_item_status_code,
  cic.item_cost,
  msib.ATTRIBUTE13

FROM oe_order_headers_all ooha,
  oe_order_lines_all oola,
  mtl_system_items_b msib,
  hz_cust_site_uses_all csu ,
  hz_cust_acct_sites_all cas ,
  hz_party_sites hps,
  mtl_parameters mp,
  cst_item_costs cic
WHERE ooha.header_id       = oola.header_id
AND oola.inventory_item_id = msib.inventory_item_id
AND oola.ship_to_org_id    = csu.site_use_id
AND csu.cust_acct_site_id  = cas.cust_acct_site_id
AND cas.party_site_id      = hps.party_site_id
AND oola.ship_from_org_id  = msib.ORGANIZATION_ID
AND msib.ORGANIZATION_ID   = mp.ORGANIZATION_ID
AND cic.inventory_item_id = msib.inventory_item_id
AND cic.ORGANIZATION_ID = msib.ORGANIZATION_ID
and cic.COST_TYPE_ID=1
AND oola.SUBINVENTORY LIKE 'Direct'
AND oola.item_type_code IN ('CONFIG','STANDARD')
AND oola.project_id       IS NOT NULL
AND OOLA.BOOKED_FLAG       = 'Y'
AND OOLA.OPEN_FLAG = 'Y' AND oola.ship_from_org_id IN
(SELECT ood.organization_id
FROM org_organization_definitions ood
WHERE ood.operating_unit =
  (SELECT operating_unit                                                        -- query to fetch operating unit
  FROM org_organization_definitions ood1
  WHERE ood1.organization_id = 2064
  )
) 
AND ooha.order_number BETWEEN NVL(5339914,ooha.order_number) AND NVL(5339914,ooha.order_number)
AND TRUNC(oola.schedule_ship_date) >= TRUNC(NVL(TO_DATE(null,'DD-MON-YYYY'),oola.schedule_ship_date))
AND TRUNC(oola.schedule_ship_date) <= TRUNC(NVL(TO_DATE(null,'DD-MON-YYYY'),oola.schedule_ship_date))

-光标选择查询结束

1 个答案:

答案 0 :(得分:2)

  

... AND ooha.order_number在NVL(:p,ooha.order_number)之间       AND NVL(:q,ooha.order_number)

嗯,这是Oracle优化的首要任务。如果绑定变量都不为null并且覆盖合理范围,则使用嵌套循环的索引范围扫描可能是一个不错的计划。但是下一次调用可能会为:p和:q指定两个空值,在这种情况下,索引范围扫描/嵌套循环计划将是灾难性的。

Oracle的最新版本(从11g,iirc开始)具有绑定感知游标和绑定敏感游标的概念。如果您想阅读该功能,则称为自适应游标共享。
有了该功能,如果您足够运行此查询,Oracle应该抓住一个事实,即不同的绑定值需要不同的计划,这样最终您的性能会更好。使用/*+ BIND_AWARE */提示可以帮助完成此过程。

老实说,我从来没有像我所希望的那样拥有这项功能。

如果需要,可以通过为优化器做一些工作来使其更轻松一些。即,将对ooha的访问分为4部分:(a)都绑定不为null,(b)p为null,q不为null,(c)p不为null,q为空,并且(d)都绑定为null

例如:

select count(*)
from   ( SELECT * 
         FROM   oe_order_headers_all ooha
         WHERE  ooha.order_number between :p and :q
         and    :p is not null
         and    :q is not null
         UNION ALL
         select *
         from   oe_order_headers_all ooha
         WHERE  ooha.order_number >= :p
         and    :p is not null
         and    :q is null
         UNION ALL
         select *
         from   oe_order_headers_all ooha
         WHERE  ooha.order_number <= :q
         and    :p is null
         and    :q is not null
         UNION ALL
         select *
         from   oe_order_headers_all ooha
         WHERE  :p is null
         and    :q is null ) ooha;

不必这样做-不幸的是需要这样做。但是,可悲的是,有时它确实有帮助,我发现它比希望/等待自适应游标共享来拯救我更快,更可靠。