Oracle 19c更改後に実行計画が変わる――パーティション削除時の統計情報更新と影響調査漏れ

トラブル

はじめに

Oracle Databaseを19cへ更改した後、最初の年次処理を終えた直後から、一部SQLの性能が急激に悪化し、夜間バッチの処理時間へ影響が及びました。

SQLもアプリケーションも変えていません。統計収集ジョブも実行していません。それにもかかわらず、実行計画だけが変わっていました。

原因は、Oracle 19cで追加された、パーティションメンテナンス時に統計情報が更新される仕様でした。従来から実施していたパーティション削除を契機として表統計の一部だけが更新され、実行計画が変化した結果、SQL性能が悪化していました。

この障害の本質は、Oracleの仕様そのものではありません。非互換情報の確認だけでは捉えられない「新機能による内部動作の変更」が、更改時の影響調査から漏れていたことです。同じ構図の見落としは、OracleでもAWSでもLinuxでも起こり得ます。

本記事では、この事例を題材に、原因調査で確認した証跡、対策の設計判断、更改プロジェクトとして追加すべき影響調査と試験の観点を整理します。

発端は更改後最初の年次処理だった

ある基幹システムでは、Oracle Databaseの更改後、最初の年次処理として保存期間を超えたデータをパーティション削除で整理していました。旧環境から長年継続している定期メンテナンスで、SQL、アプリケーション、運用手順のいずれにも性能へ影響するような変更は加えていません。

年次処理が終了した直後から、一部SQLの応答が悪化し始めました。

最初に疑ったのは、アプリケーション側の変更です。変更履歴を確認しても、性能劣化につながる修正は見つかりません。次に疑ったのは統計情報ですが、運用担当者が対象表へ統計収集を実行した記録もありませんでした。

処理内容もSQLも統計収集も、利用者側は何も変えていない。それでも更改後の環境では、SQLの性能特性だけが変わっていました。

この時点で、利用者側の変更を探す調査は行き詰まりました。残る可能性は、旧バージョンと19cの間で、Oracle内部の動作そのものが変わっていることです。調査の焦点を、アプリケーションからOracleの内部動作へ切り替えました。

Oracle 19cへの更改で顕在化した統計情報の更新

調査を進めた結果、パーティションメンテナンス時にOracleが統計情報を更新する動作が関係していることが分かりました。

この動作は、My Oracle Supportの次の文書でも、Oracle Database 19cにおけるパーティション表の統計情報変更として整理されています。

Partitioned Table Statistics Changed After Truncate Partition or Drop Partition Operation
MOS Doc ID 2970098.1

Oracle Database 19cのSQL Tuning Guideにも、パーティションメンテナンスに伴う統計情報の処理が「Online Statistics Gathering for Partition Maintenance Operations」として記載されています。

ここで区別しなければならないのは、すべてのパーティション操作で同じ統計収集処理が実行されるわけではないことです。

パーティションメンテナンスには、次のような操作があります。

  • DROP PARTITION
  • TRUNCATE PARTITION
  • MOVE PARTITION
  • MERGE PARTITION
  • COALESCE PARTITION
  • SPLIT PARTITION

MOVE PARTITIONやMERGE PARTITIONなど、データの移動やダイレクトパス書き込みを伴う処理では、操作内容に応じてオンライン統計収集が行われる場合があります。

本事例で問題となったDROP PARTITIONでは、DBMS_STATS.GATHER_TABLE_STATSに相当する全統計収集が実行されたわけではありません。パーティション削除に合わせて、グローバル表統計のNUM_ROWSやBLOCKSなどがOracle内部で更新されました。

運用担当者が統計収集ジョブを実行していなくても、統計情報の一部はパーティション操作によって変化します。

「統計情報を収集していない」という運用上の認識と、「統計情報が変化していない」というデータベース上の事実は同じではありません。

この違いを認識していなければ、性能劣化の調査でアプリケーション、SQL、負荷状況だけを追い続け、実行計画を変化させた統計情報の更新を見落とすことになります。

なぜデータを削除した後にSQLが遅くなるのか

本システムでは旧環境で同様の事象は発生しておらず、19cへの更改後に初めて顕在化しました。19cへの更改で初めて顕在化した動作です。

データを削除すれば処理対象が減るため、SQLも速くなるように思えます。

今回の事象では、パーティション削除後にSQL性能が悪化しました。

原因を理解するには、Oracleのオプティマイザが利用する統計情報を、表統計とカラム統計に分けて考える必要があります。

表統計には、表全体の規模を示す情報が含まれます。代表的な項目はNUM_ROWS、BLOCKS、AVG_ROW_LENです。

カラム統計には、列の値がどのように分布しているかを示す情報が含まれます。代表的な項目には、個別値数を示すNDV、LOW_VALUE、HIGH_VALUE、NULL数、ヒストグラムなどがあります。

DROP PARTITIONを実行すると、削除されたパーティションを反映して、表全体の行数やブロック数を示す統計が更新されます。カラム統計やヒストグラムまで、同じタイミングで整合した状態へ再収集されるわけではありません。

この状態では、オプティマイザが参照する統計情報に異なる時点の情報が混在します。

表統計は、パーティション削除後の表が以前より小さくなったことを示しています。カラム統計は、削除前の値分布を前提とした状態で残っています。

オプティマイザは、表統計とカラム統計を使って、検索条件へ該当する行数を推定します。両者の前提が一致していなければ、カーディナリティ推定が実際のデータ分布から外れる可能性があります。

カーディナリティ推定が変わると、索引を使うか全表走査を選ぶか、Nested LoopsとHash Joinのどちらを使うか、どの表を駆動表とするかといった判断も変わります。結合順序や並列実行の選択まで変化することがあります。

本件では、統計情報が更新されたという事実だけで性能が悪化したのではありません。

表統計の一部だけが更新され、既存のカラム統計との前提が一致しない状態が次回の統計収集まで残った結果、カーディナリティ推定が変化し、従来とは異なる実行計画が選択されました。

たとえば本件では、パーティション削除後にNUM_ROWSが大幅に減少した統計を基に、オプティマイザが従来とは異なるアクセスパスを選択したと推定されます。統計上は小さく見える表に対してIndex Range ScanよりFull Table Scanのコストが低いと判断されたり、結合方式がNested LoopsからHash Joinへ変わったりすることで、実業務データの実際の件数との乖離が性能劣化として現れます。

統計情報の更新は、常に性能改善を意味するものではありません。どの統計が、どの単位で、どの範囲まで更新されたのかを確認しなければ、オプティマイザが参照している情報の状態を正しく把握できません。

調査で確認した証跡

性能障害を説明するには、「パーティションを削除した」「統計情報が変わった」「SQLが遅くなった」という個別の事実だけでは十分ではありません。

重要なのは、それらの出来事が同じ時間軸で発生していることを確認することです。

今回の調査では、AWR、実行計画、統計情報の更新時刻を組み合わせ、原因と結果を時系列で整理しました。

AWRでSQL性能の変化を確認する

最初に確認したのは、AWRに記録されたSQL性能の変化です。

年次処理の終了後から対象SQLの負荷が増加しており、単純に実行回数が増えたのではなく、1回当たりの処理コストそのものが悪化していました。

主に確認した項目は次のとおりです。

  • Elapsed Time
  • CPU Time
  • Buffer Gets
  • Disk Reads
  • Executions
  • Rows Processed

これらは合計値だけでは判断できません。

たとえばElapsed Timeが増加していても、単純に実行回数が増えただけであれば異常とは言えません。

  • 1実行当たりのElapsed Time
  • 1実行当たりのBuffer Gets

まで確認し、SQLそのものの性能が変化したことを確認しました。

実行計画が変わっていないかを確認する

次に確認したのは実行計画です。

AWRやDBA_HIST_SQLSTAT、DBA_HIST_SQL_PLANを調査すると、対象SQLでは性能悪化前後でPLAN_HASH_VALUEが変化していました。

PLAN_HASH_VALUEが変わるということは、少なくともOracleが異なる実行計画を選択したことを意味します。

もちろん、PLAN_HASH_VALUEだけでは原因を断定できません。

実際には、

  • アクセスパス
  • 結合方式
  • 結合順序
  • 推定行数(Cardinality)
  • 実際の処理行数

まで確認し、オプティマイザがどの判断を変更したのかを追跡しました。

統計情報はいつ変わったのか

最後に、統計情報そのものを確認しました。

DBA_TAB_STATISTICSを見ると、パーティション削除を実施した時刻を境に、対象表の統計情報が更新されていました。

確認した主な項目は次の三つです。

  • NUM_ROWS
  • BLOCKS
  • LAST_ANALYZED

運用では統計収集ジョブを実行していないにもかかわらず、これらの値はパーティション削除のタイミングで変化していました。

さらに、DBA_TAB_COL_STATISTICSやヒストグラム関連ビューも確認したところ、カラム統計は従来の状態を保持していました。

  • 表統計は更新されている
  • カラム統計は更新されていない

という状態になっていたことが分かります。

この結果は、前章で説明した「表統計とカラム統計の前提が一致しない状態」が実際に発生していたことを裏付ける証拠となりました。

時系列で整理すると原因が見えてくる

今回の調査結果を時系列で整理すると、次の流れになります。

年次処理でDROP PARTITION
        ↓
Oracle内部で表統計の一部が更新
        ↓
表統計とカラム統計の前提が一致しない
        ↓
オプティマイザのカーディナリティ推定が変化
        ↓
実行計画が変更される
        ↓
PLAN_HASH_VALUEの変化として観測される
        ↓
Elapsed Time・Buffer Getsが増加

この流れは、一つのビューだけを見て導いたものではありません。

パーティション操作の実施時刻、統計情報の更新時刻、実行計画の変化、AWRに記録された性能指標を同じ時間軸へ並べることで、初めて因果関係を説明できます。

性能障害の調査では、「実行計画が変わった」「統計情報が更新された」という個別の事実だけを示しても説得力はありません。

複数の証跡を時系列で結び付けて初めて、性能劣化の原因を論理的に説明できます。


問題はOracleではなく影響調査の範囲だった

Oracleは仕様どおりに動作していました。

本件の問題は、パーティションメンテナンスに伴う統計情報の更新を、更改時の影響調査対象として認識できていなかったことです。

システム更改では、多くの場合、次のような項目を重点的に確認します。

  • 非互換情報
  • 廃止機能
  • Deprecated機能
  • 初期化パラメータの変更
  • サポート終了機能
  • 既知の不具合
  • SQL構文やAPIの変更

これらは重要な確認項目です。

新機能については「追加機能だから既存システムには影響しないだろう」と判断され、調査対象から外れてしまうことがあります。

今回見落としていたのは、「従来のSQLが実行できなくなる非互換」ではありませんでした。

従来と同じSQLが正常終了したまま、Oracle内部の統計情報管理だけが変わる仕様変更です。

このような仕様変更は、機能試験だけでは見つかりません。

SQLは正常終了し、処理結果も正しく、エラーログも出力されません。

実行計画や統計情報まで確認して初めて、旧バージョンとの違いが見えてきます。

更改プロジェクトでは「新機能だから影響はない」と考えるのではなく、既存処理の内部動作を変える仕様変更はないかという観点で調査することが重要になります。

このような影響調査は、構築フェーズに入ってから始めるものではありません。クラウドリフトでは、PoCや基本設計の段階で「何を調査対象に含めるか」が品質を大きく左右します。

設計前に確認すべき観点は、次の記事で詳しく解説しています。

【第1部】クラウドリフトの失敗は構築前に始まっている|PoC不足が手戻り・コスト超過・納期遅延を招く理由
AWSへのクラウドリフトで起きる手戻り、コスト超過、納期遅延は、構築中ではなくPoC不足から始まります。Auto Scaling、EFS/EBS、RDS、監視、バックアップ、ライセンスなどの設計リスクを現場目線で整理します。

技術的な対策は一つではない

本件のような事象に対して、「統計情報の更新を止めればよい」と考えるのは適切ではありません。

問題は、パーティション削除そのものではなく、統計情報の状態が変化した結果として実行計画が変わることです。

更改設計では

  • 統計情報をどのように管理するか
  • 実行計画の変化をどこまで許容するか
  • 運用でどこまで吸収するか

という三つの観点から設計する必要があります。

パーティションメンテナンス後に統計情報を再収集する

最も直接的な方法は、パーティション削除後にDBMS_STATS.GATHER_TABLE_STATSを実行し、表統計とカラム統計を同じ状態へ揃えることです。

今回の事象では、表統計だけが更新され、カラム統計との前提が一致しない状態が残ったことが実行計画変更の要因でした。

統計情報を再収集すれば、この不整合は解消されます。

統計情報を取得すれば必ず性能が改善するとは限りません。

表全体を再収集するのか、対象パーティションだけで十分なのか、インクリメンタル統計を利用するのかなど、システム特性に応じた設計は必要になります。

重要なのは、「統計情報が更新されたこと」ではなく、「統計情報の整合性をどのように維持するか」という観点で設計することです。

実行計画そのものを安定させる

統計情報を適切に管理しても、データ量や分布は時間とともに変化します。

業務影響が極めて大きいSQLについては、統計情報だけに依存せず、SQL Plan Baselineなどを利用して実行計画を管理する方法もあります。

SQL Plan Baselineは、統計情報の変化そのものを止める機能ではありません。

その代わり、十分に検証された実行計画を維持することで、予期しない計画変更による性能劣化を防ぐ役割を持ちます。

すべてのSQLを固定する運用は現実的ではありません。

長時間バッチや業務影響の大きいSQLなど、対象を限定して利用することが重要です。

Oracle内部動作を変更する方法もある

Oracleには、オンライン統計収集の動作そのものを抑止する方法も存在します。

SQL単位で抑止するのであれば、公式ドキュメントに記載されているNO_GATHER_OPTIMIZER_STATISTICSヒントが利用できます。影響範囲を特定のSQLへ限定できるため、対象処理が明確な場合には検討しやすい選択肢です。

データベース全体で抑止する方法としては、隠しパラメータである_optimizer_gather_stats_on_loadが公開されている技術情報でも言及されています。ただし、このパラメータはパーティションメンテナンス時の統計更新だけではなく、ダイレクトパスロード時を含むオンライン統計収集全体へ影響します。

隠しパラメータは、公開パラメータと同じ感覚で変更できるものではありません。バージョンやRelease Updateによって挙動が異なる可能性があり、適用の可否は自環境の構成を踏まえてOracle Supportへ確認した上で判断すべきです。

今回の事象だけを止めたつもりでも、別のバルクロード処理へ新たな影響を与えることも考えられます。抑止は最初に選ぶ対策ではなく、統計の再収集や実行計画の管理で解決できない場合の最後の選択肢として、影響範囲を十分に評価して使うべきものです。

更改設計として考えるべきこと

この事例で重要なのは、「どの対策が正しいか」を決めることではありません。

最適解はシステムによって異なることに対し、どのようなシステムでも共通する考え方があります。

パーティションメンテナンスによって統計情報が変化するのであれば、その変化を前提とした運用を設計することです。

統計情報を再収集するのか、SQL Plan Baselineで重要SQLを保護するのか、あるいはOracle内部動作まで変更するのか。

その判断は、性能要件、バッチ時間、データ量、運用体制まで含めたシステム設計として決めるべき事項です。

更改プロジェクトで追加すべき試験と運用

今回の教訓は、Oracleのチューニングだけでは終わりません。

本質的な問題は、更改プロジェクトの影響調査にありました。

多くの更改プロジェクトでは、オンライン処理や通常の日次バッチを中心に性能試験を実施します。

年次や月次にしか実行されない処理は、試験対象から外れることがあります。

パーティション削除や履歴データの整理、大量データのアーカイブなどは、その代表例です。

こうした処理は実行頻度が低いため、問題があっても更改直後には表面化しません。

今回のように、更改後最初の年次処理で初めて障害として顕在化することがあります。

更改試験では、本番データを完全に再現できないことも少なくありません。

その場合でも、DDLの実行、統計情報の変化、実行計画の変化までは十分検証できます。

さらに、更改後最初の年次処理や月次処理は通常運用として扱うのではなく、重点監視期間として計画しておくことが重要です。

SQLの実行時間だけを見るのではなく、PLAN_HASH_VALUE、統計情報の更新時刻、AWRの性能指標をあらかじめ比較できる状態にしておけば、異常が発生しても原因へたどり着くまでの時間を大幅に短縮できます。

性能障害は、発生してから調査を始めるよりも、比較するための基準値を更改前から残しておく方がはるかに効率的です。

PoCでは性能確認だけではなく、「更改後に何を比較するか」という観点で証跡を残しておくことが重要です。

PoCで確認すべき項目は、次の記事で詳しく整理しています。

【第2部・前編】クラウドリフトPoCで「動いた」は確認できた。しかし業務では使えなかった|10の設計リスク① 可用性・性能・ストレージ・バックアップ・監視
PoCで「動いた」は確認できた。しかし構築フェーズで業務が回らなかった。可用性・性能・ストレージ・バックアップ・監視の5領域で、見落とすと手戻りになる設計リスクを整理します。

非互換情報の外側にある変更を見る

この事例は、Oracle Databaseだけに当てはまる話ではありません。

システム基盤の更改では、新しいバージョンへ移行するたびに、ベンダーは性能、運用性、セキュリティ、自動化を目的として既定動作を見直しています。

たとえばAmazon RDSでは、エンジンのバージョンアップに伴って、デフォルトパラメータグループの既定値が変更されることがあります。アプリケーションを変更していなくても、データベース側の既定設定が変われば、性能や動作特性へ影響する可能性があります。

VMware vSphereでも同様です。バージョンアップに伴ってTLSの既定設定が変更され、従来は接続できていた外部システムとの通信へ影響した事例があります。システムが故障したわけではなく、製品側の既定動作が変わったことが原因でした。

Linuxでも、カーネル更新によってメモリ管理やネットワーク関連の既定動作が変更されることがあります。アプリケーションは従来どおり動作していても、OSの内部動作が変わることで性能特性が変化するケースは珍しくありません。

これらに共通しているのは、「何も変更していないのに動作が変わった」のではないという点です。

利用者は変更していなくても、ベンダーは変更しています。

更改プロジェクトでは、自分たちが修正したプログラムや設定だけに目が向きがちです。

実際には、ベンダーが変更した既定動作の方が、既存システムへ大きな影響を与えることがあります。

更改影響調査では「非互換情報」だけを見るのではなく、「既定動作は変わっていないか」という視点を同じ重みで持つ必要があります。

本記事のように、更改後に初めて表面化した仕様変更や設計上の見落としは少なくありません。

クラウドリフトやシステム更改で実際に発生したトラブル事例は、次のマガジンにまとめています。

クラウド移行でハマる、AWS設計・運用の落とし穴|ナギ @ 氷河期SEの知見録|note
AWSへのクラウド移行やDR設計で見落としやすい、設計・起動・再作成・運用の落とし穴を整理するマガジンです。 EC2、AMI、cloud-init、EC2Launch、Auto Scaling、EBS、CloudWatch Logs、S3、AWS Backupなどを題材に、「サーバは起動したのに使えない」「設定したはReadMore...

まとめ

今回の性能障害では、年次処理によるパーティション削除を契機として、Oracle内部で表統計の一部が更新されました。

表統計だけが新しい状態となり、カラム統計との前提が一致しない状態が残った結果、オプティマイザのカーディナリティ推定が変化し、実行計画も変わりました。その結果として、SQL性能が低下しました。

原因を特定できたのは、一つの情報だけを見て判断しなかったためです。

AWRで性能変化を確認し、PLAN_HASH_VALUEで実行計画の変化を追跡し、DBA_TAB_STATISTICSで統計情報の更新時刻を確認しました。それぞれを同じ時間軸へ並べることで、初めて原因と結果を論理的に説明できました。

Oracleは仕様どおりに動作していました。

問題だったのは、パーティション削除に伴う統計情報の更新という仕様変更が、更改時の影響調査対象になっていなかったことです。

更改プロジェクトで確認すべき対象は、非互換情報だけではありません。

新機能、デフォルト設定、バックグラウンド処理、内部アルゴリズムなど、既存システムへ影響を与える可能性のある仕様変更まで含めて評価する必要があります。

システム更改では、「正常終了した」ことだけでは十分とは言えません。

同じSQLが正常終了していても、実行計画や性能特性まで従来と同じとは限りません。

更改で本当に確認すべきなのは、プログラムが動くかではありません。

設計時に置いていた前提が、バージョンアップ後も成立しているかです。

システム更改の品質を左右するのは、コード変更量ではなく、前提条件の変化をどこまで洗い出せるかです。


参考資料

  • Oracle Support, Partitioned Table Statistics Changed After Truncate Partition or Drop Partition Operation(MOS Doc ID 2970098.1)
  • Oracle Database 19c SQL Tuning Guide
    (SQL Plan Management)
  • Oracle Database 19c PL/SQL Packages and Types Reference(DBMS_STATS)
  • Amazon RDS User Guide
  • VMware vSphere Release Notes

コメント

タイトルとURLをコピーしました