如何在Oracle 11g

时间:2017-08-03 11:12:02

标签: sql oracle query-performance sql-tuning

我被要求调整以下查询,并想知道是否有更好的方法来调整它?

SELECT req_dtl.lab_ord_occ_test_id ,
       req_dtl.order_ref_no ,
       req_dtl.accession_no ,
       req_dtl.test_code ,
       req_dtl.test_name ,
       req_dtl.test_id ,
       req_dtl.schedule_id ,
       req_dtl.lab_ord_occ_id ,
       req_dtl.order_type ,
       lab_occ.facility_id ,
       lab_occ.patient_id ,
       lab_occ.order_draw_dt ,
       hdr.source_system ,
      (SELECT CORPORATION_ACRONYM
       FROM corporation c,
       facility f
       WHERE c.corporation_id = f.corporation_id
       AND f.facility_id      = lab_occ.facility_id) AS corporation_acronym,
       tst.container ,
       lab_occ.order_duration_type ,
       occ_test.mnc_yn
 FROM ORDER_REQUISITION_HEADER hdr ,
      ORDER_REQUISITION_DETAIL req_dtl ,
      LAB_ORDER_OCC_TEST occ_test ,
      LAB_ORDER_OCC lab_occ ,
      TEST tst
 WHERE hdr.requisition_hdr_id       = in_requisition_hdr_id
 AND hdr.msg_sent_to_lab_yn         = 'Y'
 AND req_dtl.requisition_hdr_id     = hdr.requisition_hdr_id
 AND occ_test.lab_order_occ_test_id = req_dtl.lab_ord_occ_test_id
 AND req_dtl.test_id                = tst.test_id
 AND tst.accession_type             NOT LIKE 'CMP%'
 AND occ_test.status                      != 'R'
 AND occ_test.lab_order_occ_id             = lab_occ.lab_order_occ_id
 AND lab_occ.status                        = 'A'
 AND occ_test.created_dt                  >= hdr.msg_sent_to_lab_dt
 AND NVL(occ_test.test_sent_to_lab_yn,'N') = 'N'
 AND NOT EXISTS
              (SELECT orddata.*
               FROM MISSING_ORDER_DATA orddata,
                    TEST_CONFIG_HOLD_AOE tcha
               WHERE orddata.test_id             = tcha.test_id
               AND tcha.active_yn                = 'Y'
               AND orddata.status_flag           = 'A'
               AND orddata.answer               IS NULL
               AND orddata.msg_sent_to_lab_yn    = 'N'
               AND   orddata.lab_order_occ_test_id=occ_test.lab_order_occ_test_id
   )
   ORDER BY req_dtl.accession_no;

在执行计划中,没有表可用于全表扫描。只有嵌套循环更多。 *建议更好地调整此查询*

2 个答案:

答案 0 :(得分:0)

AND NOT EXISTS
          (SELECT orddata.*
           FROM MISSING_ORDER_DATA orddata,
                TEST_CONFIG_HOLD_AOE tcha
           WHERE orddata.test_id             = tcha.test_id
           AND tcha.active_yn                = 'Y'
           AND orddata.status_flag           = 'A'
           AND orddata.answer               IS NULL
           AND orddata.msg_sent_to_lab_yn    = 'N'
           AND   orddata.lab_order_occ_test_id=occ_test.lab_order_occ_test_id
          )

可以移到FROM

FROM 
   ... 
      LEFT JOIN (SELECT DISTINCT orddata.lab_order_occ_test_id
           FROM MISSING_ORDER_DATA orddata,
                TEST_CONFIG_HOLD_AOE tcha
           WHERE orddata.test_id             = tcha.test_id
           AND tcha.active_yn                = 'Y'
           AND orddata.status_flag           = 'A'
           AND orddata.answer               IS NULL
           AND orddata.msg_sent_to_lab_yn    = 'N'
          ) missing ON missing.lab_order_occ_test_id = occ_test.lab_order_occ_test_id
WHERE missing.lab_order_occ_test_id IS NULL

此外,你应该移动首字母缩略词

FROM
...
INNER JOIN (SELECT CORPORATION_ACRONYM, f.facility_id
   FROM corporation c,
   facility f
   WHERE c.corporation_id = f.corporation_id) acr ON 
   acr.facility_id      = lab_occ.facility_id)

答案 1 :(得分:0)

...此外,TEST对象必须具有accession_type的索引,否则tst.accession_type not like 'CMP%'子句将比必要的慢。

此外,子句:NVL(occ_test.test_sent_to_lab_yn,'N') = 'N'本质上是部分验证数据的外连接。 test_sent_to_lab_yn中的occ_test列是否包含空值?如果不是,请考虑使用IN子句和有效列表。 [它看起来像是/否专栏,也许这应该是平等的' Y'并让某人清理空值?]

请发布解释计划,以便我们建议对谓词进行重新排序,以便最小化第一个子句中的行返回....并提出HINT个建议。