如何优化查询以减少执行时间

问题描述 投票:0回答:1
SELECT
    XCRV.CROSS_REFERENCE JENIS
    ,
    XTD_INV_CONVERT_QTY_UOM_FNC (
        (select min(mcrv2.INVENTORY_ITEM_ID)
        from XTD_CROSS_REFF_ITEM_V mcrv2
        where 1=1
        and mcrv2.cross_reference = XCRV.CROSS_REFERENCE
        and mcrv2.organization_id = MMT.ORGANIZATION_ID) ,
        MMT.ORGANIZATION_ID,
        (SELECT NVL(SUM(MMT2.PRIMARY_QUANTITY), 0)
        FROM
        MTL_MATERIAL_TRANSACTIONS MMT2,
        XTD_CROSS_REFF_ITEM_V XCRV2
        WHERE 
            MMT2.ORGANIZATION_ID = XCRV2.ORGANIZATION_ID
        AND MMT2.INVENTORY_ITEM_ID = XCRV2.INVENTORY_ITEM_ID
        AND XCRV2.CROSS_REFERENCE = XCRV.CROSS_REFERENCE
        AND TRUNC(MMT2.TRANSACTION_DATE) <= TRUNC( TO_DATE( :P_DATE_FROM, 'YYYY/MM/DD' ) ) 
        ),
        MSIB.PRIMARY_UOM_CODE,
        'BAL'
    ) || '-' || XTD_INV_CONVERT_QTY_UOM_FNC (
        (select min(mcrv2.INVENTORY_ITEM_ID)
        from XTD_CROSS_REFF_ITEM_V mcrv2
        where 1=1
        and mcrv2.cross_reference = XCRV.CROSS_REFERENCE
        and mcrv2.organization_id = MMT.ORGANIZATION_ID) ,
        MMT.ORGANIZATION_ID,
        (SELECT NVL(SUM(MMT2.PRIMARY_QUANTITY), 0)
        FROM
        MTL_MATERIAL_TRANSACTIONS MMT2,
        XTD_CROSS_REFF_ITEM_V XCRV2
        WHERE 
            MMT2.ORGANIZATION_ID = XCRV2.ORGANIZATION_ID
        AND MMT2.INVENTORY_ITEM_ID = XCRV2.INVENTORY_ITEM_ID
        AND XCRV2.CROSS_REFERENCE = XCRV.CROSS_REFERENCE
        AND TRUNC(MMT2.TRANSACTION_DATE) <= TRUNC( TO_DATE( :P_DATE_FROM, 'YYYY/MM/DD' ) ) 
        ),
        MSIB.PRIMARY_UOM_CODE,
        'PRS'
    ) || '-' || XTD_INV_CONVERT_QTY_UOM_FNC (
        (select min(mcrv2.INVENTORY_ITEM_ID)
        from XTD_CROSS_REFF_ITEM_V mcrv2
        where 1=1
        and mcrv2.cross_reference = XCRV.CROSS_REFERENCE
        and mcrv2.organization_id = MMT.ORGANIZATION_ID) ,
        MMT.ORGANIZATION_ID,
        (SELECT NVL(SUM(MMT2.PRIMARY_QUANTITY), 0)
        FROM
        MTL_MATERIAL_TRANSACTIONS MMT2,
        XTD_CROSS_REFF_ITEM_V XCRV2
        WHERE 
            MMT2.ORGANIZATION_ID = XCRV2.ORGANIZATION_ID
        AND MMT2.INVENTORY_ITEM_ID = XCRV2.INVENTORY_ITEM_ID
        AND XCRV2.CROSS_REFERENCE = XCRV.CROSS_REFERENCE
        AND TRUNC(MMT2.TRANSACTION_DATE) <= TRUNC( TO_DATE( :P_DATE_FROM, 'YYYY/MM/DD' ) ) 
        ),
        MSIB.PRIMARY_UOM_CODE,
        'BKS'
    ) AS SALDO_AWAL
FROM
    MTL_MATERIAL_TRANSACTIONS MMT,
    MTL_TRANSACTION_TYPES MTT,
    MTL_SYSTEM_ITEMS_B MSIB,
    XTD_CROSS_REFF_ITEM_V XCRV,
    ORG_ORGANIZATION_DEFINITIONS OOD,
    HR_OPERATING_UNITS HOU,
    GL_LEDGERS GL
WHERE
    MMT.INVENTORY_ITEM_ID = MSIB.INVENTORY_ITEM_ID
    AND MMT.ORGANIZATION_ID = MSIB.ORGANIZATION_ID
    AND MMT.TRANSACTION_TYPE_ID = MTT.TRANSACTION_TYPE_ID
    AND MMT.ORGANIZATION_ID = OOD.ORGANIZATION_ID
    AND XCRV.INVENTORY_ITEM_ID = MMT.INVENTORY_ITEM_ID
    AND HOU.BUSINESS_GROUP_ID = OOD.BUSINESS_GROUP_ID
    AND OOD.SET_OF_BOOKS_ID = GL.LEDGER_ID
    --HARDCODE
    AND HOU.ORGANIZATION_ID NOT IN ('82')
    AND XCRV.CROSS_REFERENCE = 'ARB12'
    -- PARAMETERS
    AND GL.LEDGER_ID = NVL(:P_LEDGER, GL.LEDGER_ID)
    AND HOU.ORGANIZATION_ID = NVL(:P_OU_ID, HOU.ORGANIZATION_ID)
    AND OOD.ORGANIZATION_ID = NVL(:P_CABANG, OOD.ORGANIZATION_ID)
    -- HEADING
    AND TRUNC(MMT.TRANSACTION_DATE) BETWEEN TRUNC( TO_DATE( :P_DATE_FROM, 'YYYY/MM/DD' ))  AND TRUNC( TO_DATE( :P_DATE_TO, 'YYYY/MM/DD' )) 
GROUP BY
    XCRV.CROSS_REFERENCE,
    MMT.ORGANIZATION_ID,
    MSIB.PRIMARY_UOM_CODE
ORDER BY
    XCRV.CROSS_REFERENCE

请优化我的查询片段。当仅硬编码一条数据时,执行时间约为4分钟。不过,还有很多数据需要加载,我还有其他列需要添加。

当我尝试仅对一项数据运行查询时,附加查询大约需要 4 分钟。但是,仍有更多数据需要从数据库加载。对于结果,我希望实现较短的执行时间。

oracle plsql oracle-ebs
1个回答
0
投票

您有许多重复的子查询。您可以通过不重复它们并仅在

JOIN
子句中计算一次值而不是在
WHERE
子句中的每一行中多次计算值来提高性能:

例如,通过使用 Oracle 12 中提供的

LATERAL JOIN
(未经测试,因为您没有为所调用的函数提供示例数据或代码):

SELECT XCRV.CROSS_REFERENCE JENIS,
       XTD_INV_CONVERT_QTY_UOM_FNC(
         XCRV.min_inventory_item_idm
         mii.ORGANIZATION_ID,
         tpq.total_primary_quantity,
         MSIB.PRIMARY_UOM_CODE,
         'BAL'
       ) || '-' || XTD_INV_CONVERT_QTY_UOM_FNC (
         XCRV.min_inventory_item_idm
         mii.ORGANIZATION_ID,
         tpq.total_primary_quantity,
         MSIB.PRIMARY_UOM_CODE,
         'PRS'
       ) || '-' || XTD_INV_CONVERT_QTY_UOM_FNC (
         XCRV.min_inventory_item_idm
         mii.ORGANIZATION_ID,
         tpq.total_primary_quantity,
         MSIB.PRIMARY_UOM_CODE,
         'BKS'
       ) AS SALDO_AWAL
FROM   MTL_MATERIAL_TRANSACTIONS MMT
       INNER JOIN XTD_CROSS_REFF_ITEM_V xcrv
       CROSS JOIN LATERAL (
         select min(mcrv2.INVENTORY_ITEM_ID) AS min_inventory_item_id
         from   XTD_CROSS_REFF_ITEM_V cr
         where  cr.cross_reference = XCRV.CROSS_REFERENCE
         and    cr.organization_id = MMT.ORGANIZATION_ID
       ) miii
       CROSS JOIN LATERAL (
         SELECT COALESCE(SUM(MMT2.PRIMARY_QUANTITY), 0) AS total_primary_quantity
         FROM   MTL_MATERIAL_TRANSACTIONS MMT2
                INNER JOIN XTD_CROSS_REFF_ITEM_V XCRV2
                ON    MMT2.ORGANIZATION_ID   = XCRV2.ORGANIZATION_ID
                  AND MMT2.INVENTORY_ITEM_ID = XCRV2.INVENTORY_ITEM_ID
         WHERE  XCRV2.CROSS_REFERENCE = XCRV.CROSS_REFERENCE
         AND    MMT2.TRANSACTION_DATE < TO_DATE(:P_DATE_FROM, 'YYYY/MM/DD') + 1
       ) tpq
       INNER JOIN MTL_TRANSACTION_TYPES MTT
       ON     MMT.TRANSACTION_TYPE_ID = MTT.TRANSACTION_TYPE_ID
       INNER JOIN MTL_SYSTEM_ITEMS_B MSIB
       ON     MMT.INVENTORY_ITEM_ID = MSIB.INVENTORY_ITEM_ID
          AND MMT.ORGANIZATION_ID = MSIB.ORGANIZATION_ID
       ON     XCRV.INVENTORY_ITEM_ID = MMT.INVENTORY_ITEM_ID
       INNER JOIN ORG_ORGANIZATION_DEFINITIONS OOD
       ON     MMT.ORGANIZATION_ID = OOD.ORGANIZATION_ID
       INNER JOIN HR_OPERATING_UNITS HOU
       ON     HOU.BUSINESS_GROUP_ID = OOD.BUSINESS_GROUP_ID
       INNER JOIN GL_LEDGERS GL
       ON     OOD.SET_OF_BOOKS_ID = GL.LEDGER_ID
WHERE  --HARDCODE
       HOU.ORGANIZATION_ID NOT IN ('82')
AND    XCRV.CROSS_REFERENCE = 'ARB12'
       -- PARAMETERS
AND    (:P_LEDGER IS NULL OR GL.LEDGER_ID        = :P_LEDGER)
AND    (:P_OU_ID  IS NULL OR HOU.ORGANIZATION_ID = :P_OU_ID)
AND    (:P_CABANG IS NULL OR OOD.ORGANIZATION_ID = :P_CABANG)
       -- HEADING
AND    MMT.TRANSACTION_DATE >= TO_DATE(:P_DATE_FROM, 'YYYY/MM/DD')
AND    MMT.TRANSACTION_DATE <  TO_DATE(:P_DATE_TO,   'YYYY/MM/DD') + 1
GROUP BY
       XCRV.CROSS_REFERENCE,
       MMT.ORGANIZATION_ID,
       MSIB.PRIMARY_UOM_CODE
ORDER BY
       XCRV.CROSS_REFERENCE

您还可以直接使用

MMT.TRANSACTION_DATE
(而不是
TRUNC(MMT.TRANSACTION_DATE)
),这可能允许 Oracle 在该列上使用索引;否则您需要在
TRUNC(MMT.TRANSACTION_DATE)
上使用基于函数的索引。

© www.soinside.com 2019 - 2024. All rights reserved.