web-dev-qa-db-ja.com

2回目はOracleクエリが遅い

Oracleのパフォーマンスチューニングで見られるものについて、一般的な質問があります。テストしているクエリがあります。単純な例を提供するには大きすぎて複雑です。申し訳ありません。 (下げてみたが症状がなくなった)

初めてクエリを実行するときは2秒です。その後の時間は3、4、または5秒です。これは常に発生します-間隔を変更すると、再び2秒取得し、それから戻ります。

これは私が期待するものとは逆です-初回以降、データベースはクエリを解析する必要がなく、ブロックはバッファーキャッシュに読み込まれます。私が考えることができる唯一のことは、一時データをどこかに書き込むことです。つまり、単に読み取るよりも、書き込みと読み取りの方が高速です。しかし、それはもちろん意味がありません。

なぜこれが起こっているのか誰か知っていますか?または、このようなことを引き起こす実行計画の赤旗?

参考までに、これは複数の結合、集計、ビューを備えたSELECTです。内部PL/SQLはありません。

ありがとうございました

@Colin少なくとも一貫して、別のプロセスがこのDevマシンに影響している可能性は低いです。動的サンプリングとは何かわかりません。カーディナリティフィードバックと同じですか?

@druzinバインド変数はありませんが、述語も変更されません-同じハッシュ。

@mustaccio良い考えですが、暗黙の一時テーブルやキャッシュと関係があるのではないかと思います。やってみます。

3
orbfish

このような場合は、通常、トレースイベント10046を有効にすることで(そうする権限がある場合)、結果として得られるトレースファイルでtkprofを実行することで確実に解決できます。

alter session set events '10046 trace name context forever, level 8';
select /* try one */ -- add your SQL here and invoke it;
select /* try two */ -- add your same SQL here and invoke it;
show parameter user_dump_destination

数回起動してからトレースをオフにし、ログオフしてトレースファイルが確実に閉じられるようにします。

alter session set events '10046 trace name context off';
exit;

次に、トレースファイルを見つけて、tkprofを実行します。トレースファイル名は${Oracle_SID}_ora_39110.trcであると想定しています。

cd $Oracle_BASE/diag/rdbms/$Oracle_SID/$Oracle_SID/trace
tkprof ${Oracle_SID}_ora_39110.trc ${Oracle_SID}_ora_39110.trc.txt
vi ${Oracle_SID}_ora_39110.trc.txt

Tkprofの出力には、実行統計(論理読み取り、物理読み取りなど)が表示されます。また、tkprofの出力が役に立たない場合は、実際のトレースファイルを確認できます。

それでも問題が解決しない場合は、10053イベントを有効にして、何千行もの出力を順番に楽しむことができます。しかし、時にはそれを行う必要があります。

しかし、まず最初に(もっと簡単なこと)最初に。他の人が提案したようにしてください。テーブル統計が最新であるかどうか、オプティマイザ設定などを確認します。実行ごとにまったく同じ基準を使用している場合、オプティマイザが計画の「境界に」ある可能性があります。システム統計を収集したことを確認します。 dbms_stats.gather_system_stats pl/sqlパッケージのドキュメントを参照してください。

1
Mark Stewart

私が見るいくつかのこと:

  • CURSOR_SHARING = EXACTとCURSOR_SHARING = FORCEの間にパフォーマンスの違いはありますか?.
  • このSQL_IDの待機イベントを確認します。

    select
        event,
        time_waited "time_waited(s)",
        case when time_waited = 0 then 
            0
        else
            round(time_waited*100 / sum(time_waited) Over(), 2)
        end "percentage"
    from
        (
            select event, sum(time_waited) time_waited
            from v$active_session_history
            where sql_id = 'SQL_ID'
            group by event
        )
    order by
        time_waited desc;
    
0
hooinator

2つの実行は同じプランを使用していますか?本気ですか? autotraceは常に実際の計画を表示するわけではありません!

やってみましたか?

SELECT ... your query...;
SELECT * FROM table(DBMS_XPLAN.DISPLAY_CURSOR);

(次々と2回)

私は、DBが最初の実行に対して1つの計画を選択し、実行に基づいて別の計画を使用することを決定したと推測しています。しばらく待ってから同じクエリを再度実行するとどうなりますか?高速で動作しますか、それとも再度動作しますか?

0
David Balažic