1

データベースに対して複数の操作を実行する必要があるpreparedStatementがあるため、これらのSQLステートメントはすべて次のようなBEGIN-ENDブロックで囲まれています。

BEGIN
 DELETE FROM...WHERE A=?..
 UPDATE TABLE...WHERE B=?..
END;

しかし、多くのレビューアは、これはハード解析につながると述べました。私の理解では、ハード解析とは、共有プールにSQLが見つからない場合、構文、実行プラン、すべてを再度計算する必要があることですが、ここでは、Oracleがそれらを個別のSQLステートメントとして扱うべきではありません。オラクルが特定のSQLステートメントに対してハード解析を実行するかどうかをどのように確認できますか?

4

2 に答える 2

7

バインド変数は、SQL文と同じようにPL/SQLブロックで機能します。

これをテストするには、ループ内で単純なステートメントを実行してから、の解析カウントを確認しv$sesstatます。

挿入と削除に使用する簡単なテーブルを作成します。初期解析カウントを取得します。

create table test1(a number);

--Flush the pool, or else this test won't be repeatable.
alter system flush shared_pool;

select value, name
from v$sesstat natural join v$statname
where sid = sys_context('userenv', 'sid')
    and name in ('parse count (total)', 'parse count (hard)');

47  parse count (total)
5   parse count (hard)

これは、ハード解析がどのように見えるかです。

begin
    for i in 1 .. 10000 loop
        execute immediate 'insert into test1 values('||i||')';
    end loop;
    commit;
end;
/

select value, name
from v$sesstat natural join v$statname
where sid = sys_context('userenv', 'sid')
    and name in ('parse count (total)', 'parse count (hard)');

10072   parse count (total)
10007   parse count (hard)

バインド変数を持つPL/SQLブロックは、必ずしもハード解析されるとは限りません。解析カウントは累積的であり、ここではごくわずかしか増加しないことに注意してください。

begin
    for i in 1 .. 10000 loop
        execute immediate 
        'begin
            delete from test1 where a = :i;
        end;'
        using i;
    end loop;
    commit;
end;
/

select value, name
from v$sesstat natural join v$statname
where sid = sys_context('userenv', 'sid')
    and name in ('parse count (total)', 'parse count (hard)');

10106   parse count (total)
10019   parse count (hard)
于 2012-04-20T05:27:38.437 に答える
3

セッションをトレースしてコードを実行します。tkprofを実行し、解析番号を確認します。

バインド変数を使用しますか、それともリテラルを使用しますか?

--changeing--リテラルを使用する場合、これが解析を実行する要因の1つであるため、バインド変数をお勧めします。リテラルを変更すると、パフォーマンスが大幅に低下します。バインディングを使用してください。

これは、何が起こるかを説明および示す素晴らしいビデオです:OLTPパフォーマンス-構文解析の問題

于 2012-04-20T05:01:53.677 に答える