OracleDB性能障害。原因の7割は統計情報!(主観)
統計情報取得時の機能「ローリング無効化」(デフォルト有効)も障害の一因。
この機能と回避するための重要オプション「no_invalidate」について紹介します。
1.事象
- メンテナンスでデータ投入(10件→10,000件)。
- 更新後はデフォルト設定で統計情報を取得。
- サービス再開したら性能障害発生!
- 統計情報は取得した。原因わからない。対応わからない。
あたふたしてたら障害は解消。
DBの状態
下段はDBの状態です。
①でデータが更新され、②で統計情報が更新されます。
データと統計情報は一致。
問題なさそうですが、重要な要素がもう一つあります。
「実行計画」です。
- SQL実行前に「データ」から「統計情報」を収集しておきます。
- SQLの解析に「統計情報」を利用し「実行計画」を生成します。
- SQLの実行に「実行計画」を利用し「データ」にアクセスします。
実行計画はどのような状態だったのか。
何が問題だったのか。わかりますでしょうか
2.問題
問題は統計情報をデフォルトの設定で取得していたこと。
Oracle Database 19c のマニュアルで統計情報取得コマンド(GATHER_TABLE_STATS)を
確認すると、パラメータの中に「no_invalidate」の記載があります。
デフォルトは AUTO。ローリング無効化です。
統計が収集されるときの依存カーソルの無効化を制御します。パラメータの値は次のようになります。
・ TRUE: 依存カーソルは無効化されません。
・ FALSE: 依存カーソルは即時無効化としてマークされます。
・ AUTO: これはデフォルト値です。ローリング無効化は、一定期間にわたってすべての依存カーソルを無効化するために使用されます。データベースのパフォーマンスに対する影響は、特に多数のカーソルが無効化される場合に軽減されます。
TRUEに設定されている場合、データベースによって依存カーソルが無効化されることはありません。FALSEに設定されている場合、このプロシージャによって依存カーソルがすぐに無効化されます。
ローリング無効化とは
実行計画が即時に無効化されず、「次の実行時から最大5時間のランダムなタイミング」で無効化します。
無効化されたら次の実行時は最新の統計情報に基づいた実行計画が作成されます。(ハードパース)
それまでは統計情報取得前の実行計画が利用されます。(ソフトパース)
統計情報取得後にハードパースの負荷を分散させるための機能です。
詳細は以下 My Oracle Support ナレッジをご確認ください。
3.原因
- デフォルト設定で統計情報を取得したため、実行計画が即時に無効化され無かった。
- データ更新前の実行計画が利用され、実行計画とデータに乖離が発生したため性能障害発生。
例) データ更新前:データ量が少ないので、FULL SCAN
データ更新後:データ量が多いので、 INDES SCAN
→ FULL SCAN となり性能障害 - 最初の実行から5時間以内(ランダム)に実行計画が無効化(ローリング無効化)
- データ更新後の統計情報で実行計画が作成され事象解消
4.正しい対応
統計情報取得時に NO_INVALIDATEオプションをFALSEにしていれば
データ・統計情報・実行計画 が一致して、障害が発生しませんでした。
EXEC DBMS_STATS.GATHER_TABLE_STATS ('スキーマ名','表名', NO_INVALIDATE=>FALSE );
5.まとめ
- 特定SQLの性能障害が発生した時には3つの状態を確認しましょう。
1. データ量
2.統計情報
3.実行計画 - 統計情報を取得する際は、no_invalidate = false をつけて実行しましょう。
※実行計画を無効化しないことを無効にするので無効になります。
デフォルトはfalseの方が幸せになる人が多いと思いますが、
全然ならないですねー。
参考リンク