耗时从 400+m 到 30s 的SQL执行效率优化

最近在项目上,客户让我帮忙看一个查询很慢的视图,前提是在给我之前他们内部已进行优化了,当我看了他们的优化,其实就是简单地使用hint语句,而且并没有起到作用。
首先大概描述一下这个视图的情况,它是由三段sql union组成,总共大概220+行,里面有部分字段值是通过DBLINK获取的。详细如下:

CREATE OR REPLACE VIEW CUX_DWMS_GROUP_LOT_ITA_V AS
select t.batch_no,
       t.delivery_detail_id,
       t.order_type,
       t.virtual_ship_flag,
       t.ship_number,
       t.source_header_number,
       t.source_line_number,
       t.reference_number,
       t.party_name,
       t.ship_add,
       t.item_number,
       t.item_name,
       t.requested_quantity,
       t.picked_qty,
       t.requested_quantity_uom,
       t.pick_person,
       t.schedule_ship_date,
       t.ordered_date,
       t.organization_id,
       t.organization_code,
       t.organization_name,
       t.subinventory,
       t.ship_method_code,
       t.ship_method,
       t.released_status,
       t.line_status,
       t.remark,
       t.creation_date,
       t.printed_flag,
       t.box_count,
       t.pack_method,
       t.ship_desctiption,
       t.ddt_type
  from (SELECT /*+ leading (ooh) index(ooh ONT.OE_ORDER_HEADERS_N11) index (csi CUX.CUX_SHIP_INPUT_INFO_ITA_N01)*/
         row_number() over(partition by trh.request_number, wdd.source_header_number, wdd.source_line_number order by wdd.delivery_detail_id desc) rn,
         trh.request_number batch_no,
         wdd.delivery_detail_id,
         ott.attribute2 order_type,
         ooh.attribute9 virtual_ship_flag,
         (select csi.print_num
            from cux_ship_input_info_ita csi
           where csi.batch_num = trh.request_number
             and csi.source_header_number = wdd.source_header_number) ship_number,
         wdd.source_header_number,
         wdd.source_line_number,
         wdd.reference_number,
         ooh.attribute5 party_name,
         ool.attribute1 || '.' || ool.attribute4 ship_add,
         msib.segment1 item_number,
         msib.description item_name,
         wdd.requested_quantity,
         nvl(trl.quantity_delivered, 0) picked_qty,
         wdd.requested_quantity_uom,
         ooh.attribute6 pick_person,
         ool.schedule_ship_date,
         ooh.ordered_date,
         ood.organization_id,
         ood.organization_code,
         ood.organization_name,
         wdd.ORIGINAL_SUBINVENTORY subinventory,
         ool.attribute2 ship_method_code,
         ool.attribute3 ship_method,
         wdd.released_status,
         flv.meaning line_status,
         ooh.attribute2 remark,
         ooh.creation_date,
         decode(csi.print_flag, NULL, 'N', 'Y') printed_flag,
         csi.box_count, --件数
         csi.pack_method, --装货方式
         csi.ship_desctiption, --描述
         (select flv.lookup_code
            from fnd_lookup_values_vl                                   flv,
                 apps.cux_mid_order_header_temp_t@db_iwms.dahuatech.com cmo,
                 --apps.oe_order_headers_all@db_iwms.dahuatech.com        ooh1,
                 cux_wms_so_sync_all cws
           where cmo.freasonsforshipment = flv.MEANING
             and flv.lookup_type = 'CUX_PRINT_TEMPLATE_MAPPING'
             and cmo.fodernumber = cws.order_number
             and cws.mo_number = ooh.order_number
             and rownum<2
             /*group by flv.lookup_code*/) ddt_type
          FROM wsh_delivery_details         wdd,
               wsh_delivery_assignments     wda,
               oe_order_headers_all         ooh,
               mtl_txn_request_lines        trl,
               mtl_txn_request_headers      trh,
               ont.oe_transaction_types_all ott,
               oe_order_lines_all           ool,
               mtl_system_items_b           msib,
               org_organization_definitions ood,
               fnd_lookup_values            flv,
               cux_ship_input_info_ita      csi
         WHERE 1 = 1
           AND trh.header_id = trl.header_id
           AND trl.line_id = wdd.move_order_line_id
           AND wda.delivery_detail_id = wdd.delivery_detail_id
           AND ool.header_id = ooh.header_id
           AND ooh.order_type_id = ott.transaction_type_id
           AND wdd.source_line_id = ool.line_id
           AND wdd.source_code = 'OE'
           AND wdd.inventory_item_id = msib.inventory_item_id
           AND wdd.organization_id = msib.organization_id
           AND wdd.organization_id = ood.organization_id
           AND flv.lookup_type = 'PICK_STATUS'
           AND flv.lookup_code = wdd.released_status
           AND flv.enabled_flag = 'Y'
           AND (SYSDATE BETWEEN flv.start_date_active AND
               nvl(flv.end_date_active, SYSDATE + 2))
           AND flv.language = userenv('LANG')
           AND ooh.flow_status_code in ('BOOKED', 'CLOSED')
           AND ood.ORGANIZATION_CODE = '941'
           AND wdd.released_status in ('Y', 'C')
           AND csi.batch_num = trh.request_number
           AND csi.source_header_number = wdd.source_header_number
           ) t
 WHERE t.rn = 1
 UNION
 --样品领用
 select /*+index (csi CUX.CUX_SHIP_INPUT_INFO_ITA_N01)*/mtrh1.request_number batch_no,
        0 delivery_detail_id,
        'Move Order' order_type,
        '' virtual_ship_flag,
        '' ship_number,
        '' source_header_number,
        '' source_line_number,
        '' reference_number,
        decode(cic.Accnt_name,
               '海外内部测试',
               cic.bus_owner,
               cic.accnt_name) party_name,
        cic.addr ship_add,
        cic.part_num item_number,
        msi.description item_name,
        mtrl.quantity requested_quantity,
        mmt.transaction_quantity picked_qty,
        msi.primary_uom_code requested_quantity_uom,
        (select to_char(user_name)
           from fnd_user
          where user_id = mmt.created_by) pick_person,
        mtrh.creation_date schedule_ship_date,
        mtrh.creation_date ordered_date,
        mmt.organization_id organization_id,
        cic.out_inv_org organization_code,
        (select organization_name
           from org_organization_definitions
          where organization_code = cic.out_inv_org) organization_name,
        mmt.subinventory_code subinventory,
        '' ship_method_code,
        '' ship_method,
        '' released_status,
        '' line_status,
        '' remark,
        sysdate creation_date,
        csi.print_flag printed_flag,
        csi.box_count box_count,
        csi.pack_method pack_method,
        csi.ship_desctiption ship_desctiption,
        decode(cic.accnt_name, '海外内部测试', 'B9', 'B4') DDT_TYPE
   from apps.cux_inv_crm_move_orders@db_iwms.dahuatech.com cic,
        apps.mtl_txn_request_headers@db_iwms.dahuatech.com mtrh,
        apps.mtl_txn_request_lines@db_iwms.dahuatech.com   mtrl,
        mtl_material_transactions                          mmt,
        mtl_txn_request_headers                            mtrh1,
        mtl_txn_request_lines                              mtrl1,
        mtl_system_items_b                                 msi,
        cux_ship_input_info_ita      csi
  where cic.out_inv_org = '941'
    and cic.process_status = 'S'
    and cic.move_order_header_id = mtrh.header_id
    and cic.move_order_line_id = mtrl.line_id
    and msi.inventory_item_id = mmt.inventory_item_id
    and msi.organization_id = mmt.organization_id
    and mtrh1.header_id = mmt.transaction_source_id
    and mtrl1.header_id = mtrl1.header_id
    and mtrl1.line_id = mmt.trx_source_line_id
    and mmt.transaction_type_id = 160
    and mmt.organization_id = 270
    and mmt.transaction_quantity > 0
    and mtrl1.line_number = mtrl.line_number
    and mtrh1.request_number = 'W' || mtrh.request_number
    and mtrh1.request_number=csi.batch_num(+)
UNION
--转库,针对中部仓和米兰仓
select /*+index (csi CUX.CUX_SHIP_INPUT_INFO_ITA_N01)*/mtrh.request_number batch_no,
       0 delivery_detail_id,
       'Move Order' order_type,
       '' virtual_ship_flag,
       '' ship_number,
       '' source_header_number,
       '' source_line_number,
       '' reference_number,
       'Dahua Technology S.r.l.' party_name,
       'Via Brughetti, 9/h - 20813 Bovisio Masciago (MB)' ship_add,
       msi.segment1 item_number,
       msi.description item_name,
       mtrl.quantity requested_quantity,
       sum(mmt.transaction_quantity) picked_qty,
       msi.primary_uom_code requested_quantity_uom,
       (select to_char(user_name)
          from fnd_user
         where user_id = mmt.created_by) pick_person,
       mtrh.creation_date schedule_ship_date,
       mtrh.creation_date ordered_date,
       mmt.organization_id organization_id,
       ood.organization_code organization_code,
       ood.organization_name organization_name,
       mmt.subinventory_code subinventory,
       '' ship_method_code,
       '' ship_method,
       '' released_status,
       '' line_status,
       '' remark,
       sysdate creation_date,
       csi.print_flag printed_flag,
       csi.box_count box_count,
       csi.pack_method pack_method,
       csi.ship_desctiption ship_desctiption,
       'S1' DDT_TYPE
  from mtl_material_transactions    mmt,
       mtl_txn_request_headers      mtrh,
       mtl_txn_request_lines        mtrl,
       mtl_system_items_b           msi,
       org_organization_definitions ood,
       cux_ship_input_info_ita      csi
 where mtrh.header_id = mmt.transaction_source_id
   and mtrl.line_id = mmt.trx_source_line_id
   and mtrh.header_id = mtrh.header_id
   and mmt.organization_id = mtrh.organization_id
   and msi.inventory_item_id = mtrl.inventory_item_id
   and msi.organization_id = mmt.organization_id
   and ood.ORGANIZATION_ID = mmt.ORGANIZATION_ID
   and mmt.transaction_type_id = 115 --子库存转移
   and mmt.organization_id = 270
   and mmt.transaction_quantity > 0
   and ((mtrl.to_subinventory_code = '91.02.01' and
       mtrl.from_subinventory_code = '91.02.02') or
       (mtrl.to_subinventory_code = '91.02.02' and
       mtrl.from_subinventory_code = '91.02.01'))
   and mtrh.request_number = csi.batch_num
   and not exists (select 1
          from mtl_txn_request_lines mtrl1
         where mtrl1.line_id = mtrl.line_id
           and mtrl1.line_status = ('7')) --确保搬运单行没有打开状态
--and mtrh.request_number = 'W10194646'
 group by mtrh.request_number,
          msi.segment1,
          msi.description,
          mtrl.quantity,
          msi.primary_uom_code,
          mmt.created_by,
          mtrh.creation_date,
          mtrh.creation_date,
          mmt.organization_id,
          ood.organization_code,
          ood.organization_name,
          mmt.subinventory_code ,
          csi.print_flag,
          csi.box_count,
          csi.pack_method,
          csi.ship_desctiption;

其次,在plsql里查询了一下这个视图,200+分钟过去了没有执行出结果,终于等到跑完打出trace日志文件。这段SQL出来的结果只有6条数据,为什么耗时这么长呢?
耗时从 400+m 到 30s 的SQL执行效率优化
耗时从 400+m 到 30s 的SQL执行效率优化
最后,我来说说我的sql优化思路吧

  • 一般Sql优化都得从根入手,进行SQL调整,大多数技术或顾问或客户在写SQL时都是只顾执行结果不顾其在时间/空间等性能,所以大多数SQL都是千疮百孔的经不起推敲,那么在进行SQL调整的前提是确保结果正确。SQL调整目的在于两点 :1、利用Oracle中的数据集驱动,让数据量小的结果集为主,关联其他表或对象;2、让where子句条件走索引,尽量走结果集小的索引。调整过后的视图如下:
CREATE OR REPLACE VIEW CUX_DWMS_GROUP_LOT_ITA_V AS
select t.batch_no,
       t.delivery_detail_id,
       t.order_type,
       t.virtual_ship_flag,
       t.ship_number,
       t.source_header_number,
       t.source_line_number,
       t.reference_number,
       t.party_name,
       t.ship_add,
       t.item_number,
       t.item_name,
       t.requested_quantity,
       t.picked_qty,
       t.requested_quantity_uom,
       t.pick_person,
       t.schedule_ship_date,
       t.ordered_date,
       t.organization_id,
       t.organization_code,
       t.organization_name,
       t.subinventory,
       t.ship_method_code,
       t.ship_method,
       t.released_status,
       t.line_status,
       t.remark,
       t.creation_date,
       t.printed_flag,
       t.box_count,
       t.pack_method,
       t.ship_desctiption,
       t.ddt_type
  from (SELECT row_number() over(partition by trh.request_number, wdd.source_header_number, wdd.source_line_number order by wdd.delivery_detail_id desc) rn,
               trh.request_number batch_no,
               wdd.delivery_detail_id,
               (select ott.attribute2
                  from ont.oe_transaction_types_all ott
                 where ooh.order_type_id = ott.transaction_type_id) order_type,
               ooh.attribute9 virtual_ship_flag,
               (select csi.print_num
                  from cux_ship_input_info_ita csi
                 where csi.batch_num = trh.request_number
                   and csi.source_header_number = wdd.source_header_number) ship_number,
               wdd.source_header_number,
               wdd.source_line_number,
               wdd.reference_number,
               ooh.attribute5 party_name,
               ool.attribute1 || '.' || ool.attribute4 ship_add,
               msib.segment1 item_number,
               msib.description item_name,
               wdd.requested_quantity,
               nvl(trl.quantity_delivered, 0) picked_qty,
               wdd.requested_quantity_uom,
               ooh.attribute6 pick_person,
               ool.schedule_ship_date,
               ooh.ordered_date,
               ood.organization_id,
               ood.organization_code,
               ood.organization_name,
               wdd.original_subinventory subinventory,
               ool.attribute2 ship_method_code,
               ool.attribute3 ship_method,
               wdd.released_status,
               (select flv.meaning
                  from fnd_lookup_values_vl flv
                 where 1 = 1
                   AND flv.lookup_type = 'PICK_STATUS'
                   AND flv.lookup_code = wdd.released_status
                   AND flv.enabled_flag = 'Y'
                   AND (SYSDATE BETWEEN flv.start_date_active AND
                       nvl(flv.end_date_active, SYSDATE + 2))) line_status,
               ooh.attribute2 remark,
               ooh.creation_date,
               decode(csi.print_flag, NULL, 'N', 'Y') printed_flag,
               csi.box_count, --件数
               csi.pack_method, --装货方式
               csi.ship_desctiption, --描述
               (select flv.lookup_code
                  from fnd_lookup_values_vl                                   flv,
                       apps.cux_mid_order_header_temp_t@db_iwms.dahuatech.com cmo,
                       cux_wms_so_sync_all                                    cws -- 不走T2索引
                 where cmo.freasonsforshipment = flv.MEANING
                   and flv.lookup_type = 'CUX_PRINT_TEMPLATE_MAPPING'
                   and cmo.fodernumber = cws.order_number
                   and cws.mo_number = ooh.order_number
                   and rownum = 1) ddt_type
          FROM wsh_delivery_details         wdd,
               oe_order_headers_all         ooh,
               oe_order_lines_all           ool,
               mtl_txn_request_lines        trl,
               mtl_txn_request_headers      trh,
               mtl_system_items_b           msib,
               org_organization_definitions ood,
               cux_ship_input_info_ita      csi
         WHERE 1 = 1
           and wdd.source_header_id = ooh.header_id
           AND wdd.source_line_id = ool.line_id
           AND wdd.source_code = 'OE'
           AND wdd.released_status in ('Y', 'C')
           and wdd.inventory_item_id = ool.inventory_item_id
           AND wdd.move_order_line_id = trl.line_id
           and wdd.inventory_item_id = trl.inventory_item_id
           and wdd.organization_id = trl.organization_id
           AND wdd.inventory_item_id = msib.inventory_item_id
           AND wdd.organization_id = msib.organization_id
           AND wdd.organization_id = ood.organization_id
           AND trh.header_id = trl.header_id
           AND ooh.header_id = ool.header_id
           AND ooh.flow_status_code in ('BOOKED', 'CLOSED')
           AND ood.organization_id = 270
           AND csi.batch_num = trh.request_number
           AND csi.source_header_number = wdd.source_header_number) t
 WHERE t.rn = 1

UNION
--样品领用
select wms_temp.request_number batch_no,
       0 delivery_detail_id,
       'Move Order' order_type,
       '' virtual_ship_flag,
       '' ship_number,
       '' source_header_number,
       '' source_line_number,
       '' reference_number,
       decode(ebs_temp.accnt_name,
              '海外内部测试',
              ebs_temp.bus_owner,
              ebs_temp.accnt_name) party_name,
       ebs_temp.addr ship_add,
       ebs_temp.part_num item_number,
       wms_temp.description item_name,
       ebs_temp.quantity requested_quantity,
       wms_temp.transaction_quantity picked_qty,
       wms_temp.primary_uom_code requested_quantity_uom,
       (select to_char(user_name)
          from fnd_user
         where user_id = wms_temp.created_by) pick_person,
       ebs_temp.creation_date schedule_ship_date,
       ebs_temp.creation_date ordered_date,
       wms_temp.organization_id organization_id,
       ebs_temp.out_inv_org organization_code,
       (select organization_name
          from org_organization_definitions
         where organization_code = ebs_temp.out_inv_org) organization_name,
       wms_temp.subinventory_code subinventory,
       '' ship_method_code,
       '' ship_method,
       '' released_status,
       '' line_status,
       '' remark,
       sysdate creation_date,
       csi.print_flag printed_flag,
       csi.box_count box_count,
       csi.pack_method pack_method,
       csi.ship_desctiption ship_desctiption,
       decode(ebs_temp.accnt_name, '海外内部测试', 'B9', 'B4') ddt_type
  from (select cic.addr,
               cic.part_num,
               mtrl.quantity,
               mtrh.creation_date,
               mtrh.request_number,
               mtrl.line_number,
               cic.out_inv_org,
               cic.bus_owner,
               cic.accnt_name
          from apps.cux_inv_crm_move_orders@db_iwms.dahuatech.com cic,
               apps.mtl_txn_request_headers@db_iwms.dahuatech.com mtrh,
               apps.mtl_txn_request_lines@db_iwms.dahuatech.com   mtrl
         where cic.out_inv_org = '941'
           and cic.process_status = 'S'
           and cic.move_order_header_id = mtrh.header_id
           and cic.move_order_line_id = mtrl.line_id
           and mtrh.header_id = mtrl.line_id) ebs_temp,
       (select mtrh1.request_number,
               mtrl1.line_number,
               msi.description,
               mmt.transaction_quantity,
               msi.primary_uom_code,
               mmt.created_by,
               mmt.organization_id,
               mmt.subinventory_code
          from mtl_material_transactions mmt,
               mtl_txn_request_headers   mtrh1,
               mtl_txn_request_lines     mtrl1,
               mtl_system_items_b        msi
         where 1 = 1
           and msi.inventory_item_id = mmt.inventory_item_id
           and msi.organization_id = mmt.organization_id
           and mtrh1.header_id = mmt.transaction_source_id
           and mtrl1.header_id = mtrl1.header_id
           and mtrl1.line_id = mmt.trx_source_line_id
           and mmt.transaction_type_id = 160
           and mmt.organization_id = 270
           and mmt.transaction_quantity > 0) wms_temp,
       cux_ship_input_info_ita csi
 where 1 = 1
   and wms_temp.line_number = ebs_temp.line_number
   and wms_temp.request_number = 'W' || ebs_temp.request_number
   and wms_temp.request_number = csi.batch_num(+)

UNION
--转库,针对中部仓和米兰仓
select mmt_temp.batch_no,
       0 delivery_detail_id,
       'Move Order' order_type,
       '' virtual_ship_flag,
       '' ship_number,
       '' source_header_number,
       '' source_line_number,
       '' reference_number,
       'Dahua Technology S.r.l.' party_name,
       'Via Brughetti, 9/h - 20813 Bovisio Masciago (MB)' ship_add,
       mmt_temp.item_number,
       mmt_temp.item_name,
       mmt_temp.requested_quantity,
       mmt_temp.picked_qty,
       mmt_temp.requested_quantity_uom,
       (select to_char(user_name)
          from fnd_user
         where user_id = mmt_temp.created_by) pick_person,
       mmt_temp.creation_date schedule_ship_date,
       mmt_temp.creation_date ordered_date,
       mmt_temp.organization_id,
       ood.organization_code organization_code,
       ood.organization_name organization_name,
       mmt_temp.subinventory,
       '' ship_method_code,
       '' ship_method,
       '' released_status,
       '' line_status,
       '' remark,
       sysdate creation_date,
       csi.print_flag printed_flag,
       csi.box_count box_count,
       csi.pack_method pack_method,
       csi.ship_desctiption ship_desctiption,
       'S1' ddt_type
  from (select mtrh.request_number batch_no,
               msi.segment1 item_number,
               msi.description item_name,
               mtrl.quantity requested_quantity,
               sum(mmt.transaction_quantity) picked_qty,
               msi.primary_uom_code requested_quantity_uom,
               mmt.created_by,
               mtrh.creation_date,
               mmt.organization_id,
               mmt.subinventory_code subinventory
          from mtl_material_transactions mmt,
               mtl_txn_request_headers   mtrh,
               inv.mtl_txn_request_lines mtrl,
               mtl_system_items_b        msi
         where 1 = 1
           and mmt.transaction_source_id = mtrh.header_id
           and mmt.trx_source_line_id = mtrl.line_id
           and mmt.organization_id = mtrl.organization_id
           and mmt.inventory_item_id = msi.inventory_item_id
           and mmt.organization_id = msi.organization_id
           and mtrh.header_id = mtrl.header_id
           and mmt.transaction_type_id = 115 --子库存转移
           and mmt.transaction_quantity > 0
           and mmt.organization_id = 270
           and ((mtrl.to_subinventory_code = '91.02.01' and
               mtrl.from_subinventory_code = '91.02.02') or
               (mtrl.to_subinventory_code = '91.02.02' and
               mtrl.from_subinventory_code = '91.02.01'))
           and mtrl.line_status <> '7' --确保搬运单行没有打开状态
         group by mtrh.request_number,
                  msi.segment1,
                  msi.description,
                  mtrl.quantity,
                  msi.primary_uom_code,
                  mmt.created_by,
                  mtrh.creation_date,
                  mmt.organization_id,
                  mmt.subinventory_code) mmt_temp,
       org_organization_definitions ood,
       cux_ship_input_info_ita csi
 where 1 = 1
   and mmt_temp.batch_no = csi.batch_num
   and mmt_temp.organization_id = ood.organization_id;

调整过后,cost 从 383.4w 降到了 1.8w。

  • sql调整后再次查询视图,其执行时间并不理想,故而得通过trace文件去分析了。
    耗时从 400+m 到 30s 的SQL执行效率优化
    这里是select结果上的子查询,其表的T2索引是建在order_number字段上的,而且此处还有dblink。首先强烈建议客户调整一下此处取值sql,最不济的办法是用hint指定索引。
    耗时从 400+m 到 30s 的SQL执行效率优化
    这处也需要调整,但看了其sql和表上索引字段【move_order_line_id】,也并无不妥,如果一定要调整,只有调整索引,建在move_order_line_id 和released_status上缩小结果集,但个人不是很建议,理由后续。

如上调整后,执行时间控制在了20-50秒内。
耗时从 400+m 到 30s 的SQL执行效率优化

上一篇:用python解析csi数据,使用csi tools工具获取wifi的.dat文件


下一篇:Raspiberry +CSI摄像头 拍照或录制视频