1

検索機能に使用される以下のOracle SQLクエリがあり、ストアドプロシージャにラップされています。

動作が非常に遅いです。

OPEN p_cursor for SELECT TableA.*、TB_S.someColumn、TB_S.SomeColumn ..

    FROM
        customer_site TableA
        LEFT JOIN TableB TB on TB.some_id = TableA.some_id
        LEFT JOIN TableC TB_S on TB_S.Bla_ID = TB.Bla_ID
        LEFT JOIN TableC TB_CS on TB_CS.Bla2_ID = TB.Bla2_ID
        LEFT JOIN TableC TB_1 on TB_1.Bla3_ID = TB.Bla3_ID
        LEFT JOIN TableC TB_2 on TB_DC.Bla4_ID = TB.Bla4_ID
        LEFT JOIN TableD SP on SP.SP_ID = TableA.SP_ID
        LEFT JOIN TableC TB_3 on TB_3.Bla5_ID = TB.Bla5_ID
        LEFT JOIN TableC TB_4 on TB_4.Bla6_ID = TB.Bla6_ID
        LEFT JOIN TableC TB_5 on TB_5.Bla7_ID = TB.Bla7_ID
    WHERE 
        (p_nmi IS NULL OR TableA.someid LIKE p_nmi)
        AND (p_last_name IS NULL OR TableA.last_name LIKE p_last_name)
        AND (p_full_address IS NULL OR
            UPPER(assemble_address(flat_number, street_number, street_name,
                street_suffix, apartment_number, building_name, suburb, state, postcode))
            LIKE p_full_address)
        AND (p_param1 IS NULL OR TB.owner = p_param1)
        AND (p_param2 IS NULL OR TB.status = p_param2)
        AND (p_param3 IS NULL OR TB.contact_stage = p_param3)
        AND (p_param4 IS NULL OR TB.no_access_code = p_param4)
        AND (p_param5 IS NULL OR TB.defect_code = p_param5)
        AND (p_param6 IS NULL OR TB.REFUSAL_RESOLUTION = p_param6)
        AND (p_param7 IS NULL OR TB.DEFECT_LEVEL = p_param7)
        AND (p_param8 IS NULL OR TB.AMI_CTR_STATUS = p_param8)
        AND (p_param9 IS NULL OR TableA.meter_route LIKE p_param9)
        AND (p_param10 IS NULL OR TableA.sp_id = p_param10)
        AND (p_inTBdent_date_from IS NULL OR TB.inTBdent_date >= p_inTBdent_date_from)
        AND (p_inTBdent_date_to IS NULL OR TB.inTBdent_date <= p_inTBdent_date_to)
        AND rownum < 1001
    ORDER BY
        TB.inTBdent_date;

DB の専門家が上記のクエリを調整する方法を教えてくれませんか?

ありがとうございました。

4

1 に答える 1

1

@Annjawn が示唆したように、 のすべてのインスタンスを に変更し(p_param IS NULL or col = p_param)ますcol = nvl(p_param, col)。オラクルは、このジョナサン・ルイスの記事で説明されているように、これらの条件を最適化できます。INDEX RANGE SCANこれにより、 の代わりにが有効になる場合がありTABLE ACCESS FULLます。NOT NULLただし、その変更は、列がである場合にのみ論理的に同等です。これは、 null = nulltrue を返さないためです。(個人的には条件の書き方の方が好きですが、Oracle は OR を嫌うようです。)

それでも問題が解決しない場合は、説明計画を投稿して、実際の問題を特定してください。まず、手順を変更してヒントを追加しSELECT /*+ gather_plan_statistics */ TableA.*, ...ます。プロシージャを実行し、次のようなクエリで関連する SQL_ID を見つけますselect * from v$sql where lower(sql_fulltext) like '%gather_plan_statistics%';。最後に、 の結果を投稿します select * from table(dbms_xplan.display_cursor(sql_id => '<sql_id from previous step>', format => 'allstats last'));。これにより、実行計画と、おそらくオプティマイザーが行っている不適切な決定がわかります。

于 2014-02-05T04:47:59.633 に答える