GV$OB_SQL_AUDITは最も一般的に使用されるSQLモニタリングビューであり、各SQLリクエストのソース、実行状態、リソース消費量、および待機イベントを記録することができます。さらに、SQLテキストや実行計画などの重要な情報も記録されています。このビューは、SQL問題を診断するための強力なツールです。
このビューには多くのフィールドがあり、段階的に紹介します。主なフィールドの説明は以下の通りです:
TENANT_ID:リクエストのテナントID。SVR_IP:リクエストを受け付けたサーバーノードのIPアドレス。CLIENT_IP:リクエストを送信したクライアントのIPアドレス。REQUEST_TIME:リクエスト到着時間。REQUEST_ID:リクエストのIDであり、リクエストの実行を識別し、時間とともに増加します。外部モニタリングシステムはこのフィールドをカーソルとして使用して監査情報を取得できます。IS_INNER_SQL:内部SQLリクエストかどうか。IS_EXECUTOR_RPC:現在のリクエストがRPCリクエストかどうか。SQL_ID:特定のSQLを識別するものであり、同一SQLの複数回の実行では同じSQL_IDと異なるREQUEST_IDを持ちます。QUERY_SQL:SQL文の完全なテキスト。OceanBaseデータベースはSQL_IDとSQL_TEXTを使用して実行計画をバインドすることをサポートしています。SID:セッションを識別するものであり、その接続上のすべてのSQLおよび待機イベントに関連付けることができます。これはGV$OB_PROCESSLISTビューのIDフィールドに対応します。TX_ID:トランザクションを識別するものであり、そのトランザクションのすべてのSQLに関連付けることができます。トランザクション内で連続して実行される2つのSQLの開始時刻と終了時刻に大きな差がある場合、チェーン上の時間消費が大きいことを示します。TRACE_ID:このSQLリクエストのtrace IDであり、他のモニタリング指標やログの照会に関連付けることができます。IS_hit_PLAN:Plan Cache内のPlanにヒットしたかどうか。SQLの最適化は時間がかかるため、繰り返しSQLの最適化を避けるために、生成されたPlanをPlan Cacheに格納し、再度実行する際には直接Plan CacheからPlanを取得します。Plan Cacheにヒットしない場合をハードパースと呼び、Plan Cacheにヒットした場合をソフトパースと呼びます。ハードパースはSQL性能に影響を与え、時間消費を増加させます。テナントのPlan Cacheヒット率が低すぎる場合は、Plan Cacheの空き容量が小さすぎてPlanが頻繁に破棄されていないか確認する必要があります。PLAN_ID:実行計画のIDであり、その計画の詳細情報や統計情報を照会することができます。PLAN_HASH:実行計画のHash値。PLAN_TYPE:実行計画のタイプであり、値は0、1、2、3です。そのうち:1、2、3はそれぞれローカル計画、リモート計画、分散計画に対応し、0は実行計画なしを示します。例えば、commit文などです。AFFECTED_ROWS:影響を受ける行数。RETURN_ROWS:返される行数。RET_CODE:実行結果の返却コード。EVENT:最長待機イベント名。P1TEXT ~ P3TEXT:待機イベントパラメータ1〜3。P1 ~ P3:待機イベントパラメータの値1〜3。LEVEL:待機イベントのレベル。WAIT_CLASS_ID:待機イベントが属するカテゴリのID。WAIT_CLASS:待機イベントが属するカテゴリ名。STATE:待機イベントの状態。WAIT_TIME_MICRO:この待機イベントが待機した時間(マイクロ秒)。TOTAL_WAIT_TIME_MICRO:実行プロセス全体の待機時間の合計(マイクロ秒)。TOTAL_WAITS:実行プロセス全体の待機回数。ELAPSED_TIME:今回の実行の合計時間(リクエストから実行終了まで)、複数のサブフェーズで構成されます:NET_TIME:RPCの送信からリクエストの受信までの時間。NET_WAIT_TIME:リクエストの受信からキューへの入列までの時間。QUEUE_TIME:キュー時間であり、現在のテナントのリクエストの積み残し状況を反映します。DECODE_TIME:キューからの出列後のデコード時間。GET_PLAN_TIME:実行計画の生成時間であり、現在のテナントのPlan Cacheの健全性を反映します。EXECUTE_TIME:計画の実行時間。
EXECUTE_TIME:今回の実際の実行時間であり、CPU時間とTOTAL_WAIT_TIME_MICROで構成されます。TOTAL_WAIT_TIME_MICROはAPPLICATION_WAIT_TIME、CONCURRENCY_WAIT_TIME、USER_IO_WAIT_TIME、SCHEDULE_TIMEなどのいくつかの部分で構成されます。EXECUTE_TIMEは実際に費やされた実行の合計時間であり、CPU計算に必要な時間(CPU_TIME)と各種待機時間(TOTAL_WAIT_TIME_MICRO)を含みます。APPLICATION_WAIT_TIME:すべてのapplicationクラスイベントの合計時間。CONCURRENCY_WAIT_TIME:すべてのconcurrencyクラスイベントの合計時間。USER_IO_WAIT_TIME:すべてのuser_ioクラスイベントの合計時間。SCHEDULE_TIME:すべてのscheduleクラスイベントの時間。
- ロジック読み取り:リクエストの実行中にデータを読み取る際、まず各レベルのキャッシュ(
ROW_CACHE_HIT、BLOOM_FILTER_CACHE_HIT、BLOCK_CACHE_HITなどのフィールドに対応)を読み取ります。すべてヒットしない場合、実際のディスク読み取り(DISK_READSフィールドに対応)が発生します。キャッシュ読み取り回数とディスク読み取り回数を統計することで、そのリクエストの実行プロセスでスキャンされる行数を求めることができます(スキャンされる行数は実際の物理読み取りとは等しくなく、まず各レベルのキャッシュがスキャンされます)。これにより、そのSQLが最適化が必要かどうかを判断できます。ROW_CACHE_HIT:行キャッシュのヒット回数。BLOOM_FILTER_CACHE_HIT:bloom filterキャッシュのヒット回数。BLOCK_CACHE_HIT:ブロックキャッシュのヒット回数。DISK_READS:物理読み取り回数。
RETRY_CNT:再試行回数。TABLE_SCAN:そのリクエストにフルテーブルスキャンが含まれているかどうかを判断します。CONSISTENCY_LEVEL:一貫性レベル。MEMSTORE_READ_ROW_COUNT:MemStoreで読み取られた行数。SSSTORE_READ_ROW_COUNT:SSStoreで読み取られた行数。REQUEST_MEMORY_USED:そのリクエストで消費されたメモリ。PLSQL_COMPILE_TIME:PLコンパイルに要した時間。INSERT_DUPLICATE_ROW_COUNT:insertupまたはreplace into時の重複行数を記録します
GV$OB_SQL_AUDITビューのデータは、設定可能なメモリ領域に格納されており、各テナントは各ノード上に独立したキャッシュを持っています。メモリ使用量または記録数が破棄上限に達すると自動破棄がトリガーされ、最も古いデータが優先的に破棄されます。経験豊富なDBAは、SQL問題を調査する際、最初にSQL Audit機能を無効にして現場を保存し、モニタリングデータのジッター現象による破棄を防ぐことがよくあります。
以下のパラメータを使用して、SQL Audit機能の動作を制御できます:
enable_sql_audit:クラスタ構成パラメータであり、すべてのテナントのSQL Audit機能を有効にするかどうかを動的に有効にします。ob_enable_sql_audit:テナントレベルのシステム変数であり、現在のテナントでSQL Audit機能を有効にするかどうかを動的に有効にします。ob_sql_audit_percentage:テナントレベルのシステム変数であり、現在のテナントのSQL Audit機能がテナントメモリの何パーセントを占めるかを動的に有効にします。SQL Auditがメモリを過剰に占有するのを防ぐため、システムはそのメモリ上限を1GBに設定しています。
GV$OB_SQL_AUDITビューを使用すると、SQL実行のさまざまな次元の情報を容易に照会できます。
実行時間が100msを超えるSQLを照会します。
obclient> select request_id,usec_to_time(request_time),ELAPSED_TIME,QUEUE_TIME,EXECUTE_TIME,query_sql from v$OB_SQL_AUDIT where ELAPSED_TIME > 100000 limit 10; +------------+----------------------------+--------------+------------+--------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ | request_id | usec_to_time(request_time) | ELAPSED_TIME | QUEUE_TIME | EXECUTE_TIME | query_sql | +------------+----------------------------+--------------+------------+--------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ | 1538599798 | 2023-03-08 11:00:46.089711 | 335152 | 462 | 329196 | select request_id,usec_to_time(request_time),ELAPSED_TIME,QUEUE_TIME,EXECUTE_TIME,query_sql from v$OB_SQL_AUDIT where ELAPSED_TIME > 100000 limit 10 | | 1538601580 | 2023-03-08 11:00:47.411316 | 276913 | 1420 | 275345 | select request_id,usec_to_time(request_time),ELAPSED_TIME,QUEUE_TIME,EXECUTE_TIME,query_sql from v$OB_SQL_AUDIT where ELAPSED_TIME > 100000 limit 10 | | 1538603976 | 2023-03-08 11:00:49.258464 | 154873 | 461 | 154236 | select request_id,usec_to_time(request_time),ELAPSED_TIME,QUEUE_TIME,EXECUTE_TIME,query_sql from v$OB_SQL_AUDIT where ELAPSED_TIME > 100000 limit 10 | | 1538613501 | 2023-03-08 11:00:56.123111 | 188973 | 688 | 188144 | select request_id,usec_to_time(request_time),ELAPSED_TIME,QUEUE_TIME,EXECUTE_TIME,query_sql from v$OB_SQL_AUDIT where ELAPSED_TIME > 100000 limit 10 | | 1538712684 | 2023-03-08 11:02:07.504777 | 288516 | 1137 | 287180 | select request_id,usec_to_time(request_time),ELAPSED_TIME,QUEUE_TIME,EXECUTE_TIME,query_sql from v$OB_SQL_AUDIT where ELAPSED_TIME > 100000 limit 10 | | 1538743161 | 2023-03-08 11:02:29.135127 | 289585 | 26 | 289380 | select request_id,usec_to_time(request_time),ELAPSED_TIME,QUEUE_TIME,EXECUTE_TIME,query_sql from v$OB_SQL_AUDIT where ELAPSED_TIME > 100000 limit 10 | | 1538749786 | 2023-03-08 11:02:33.890317 | 294356 | 45 | 294180 | select request_id,usec_to_time(request_time),ELAPSED_TIME,QUEUE_TIME,EXECUTE_TIME,query_sql from v$OB_SQL_AUDIT where ELAPSED_TIME > 100000 limit 10 | | 1538792259 | 2023-03-08 11:03:04.626596 | 192843 | 128 | 192569 | select request_id,usec_to_time(request_time),ELAPSED_TIME,QUEUE_TIME,EXECUTE_TIME,query_sql from v$OB_SQL_AUDIT where ELAPSED_TIME > 100000 limit 10 | | 1538799117 | 2023-03-08 11:03:09.567622 | 201594 | 55 | 201388 | select request_id,usec_to_time(request_time),ELAPSED_TIME,QUEUE_TIME,EXECUTE_TIME,query_sql from v$OB_SQL_AUDIT where ELAPSED_TIME > 100000 limit 10 | | 1538804299 | 2023-03-08 11:03:13.274090 | 235720 | 241 | 235302 | select request_id,usec_to_time(request_time),ELAPSED_TIME,QUEUE_TIME,EXECUTE_TIME,query_sql from v$OB_SQL_AUDIT where ELAPSED_TIME > 100000 limit 10 | +------------+----------------------------+--------------+------------+--------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ 10 rows in set (0.28 sec)最近1000件のSQLの平均キュー待機時間を照会します。
obclient> select /*+ query_timeout(30000000) */ avg(queue_time) from v$OB_SQL_AUDIT where request_id > (select max(request_id) from v$OB_SQL_AUDIT) - 1000 ; +-----------------+ | avg(queue_time) | +-----------------+ | 350.8740 | +-----------------+ 1 row in set (0.26 sec)テナントリソースを最も多く消費するSQLを照会し、
実行時間 × 実行回数で降順にソートします。テナントに現在容量不足(テナントCPU利用率が飽和)がある場合、このステートメントを使用してSQL問題や疑わしいSQLであるかどうかを判断できます。obclient> select SQL_ID, avg(ELAPSED_TIME), avg(QUEUE_TIME), avg(ROW_CACHE_HIT + BLOOM_FILTER_CACHE_HIT + BLOCK_CACHE_HIT + DISK_READS) avg_logical_read, avg(execute_time) avg_exec_time, count(*) cnt, avg(execute_time - TOTAL_WAIT_TIME_MICRO ) avg_cpu_time, avg( TOTAL_WAIT_TIME_MICRO ) avg_wait_time, WAIT_CLASS, avg(retry_cnt) from v$OB_SQL_AUDIT group by 1 order by avg_exec_time * cnt desc limit 10; +----------------------------------+-------------------+-----------------+------------------+---------------+--------+--------------+---------------+------------+----------------+ | SQL_ID | avg(ELAPSED_TIME) | avg(QUEUE_TIME) | avg_logical_read | avg_exec_time | cnt | avg_cpu_time | avg_wait_time | WAIT_CLASS | avg(retry_cnt) | +----------------------------------+-------------------+-----------------+------------------+---------------+--------+--------------+---------------+------------+----------------+ | 2705182A6EAB699CEC8E59DA80710B64 | 54976.9269 | 43.8605 | 17664.2727 | 54821.5828 | 11759 | 54821.5828 | 0.0000 | OTHER | 0.0000 | | 32AB97A0126F566064F84DDDF4936F82 | 1520.9832 | 380.7903 | 63.7847 | 789.6781 | 63632 | 789.6781 | 0.0000 | OTHER | 0.0000 | | A5F514E873BE9D1F9A339D0DA7481D69 | 44032.5553 | 44.5149 | 8943.7834 | 43878.1405 | 1039 | 43878.1405 | 0.0000 | OTHER | 0.0000 | | 31FD78420DB07C11C8E3154F1658D237 | 7769857.0000 | 35.7500 | 399020.7500 | 7769682.7500 | 4 | 7769682.7500 | 0.0000 | NETWORK | 1.0000 | | C48AEE941D985D8DEB66892228D5E845 | 8528.6227 | 0.0000 | 0.0000 | 8450.4047 | 1601 | 8450.4047 | 0.0000 | OTHER | 0.0000 | | 101B7B79DFA9AE801BEE4F1A234AD294 | 158.2296 | 41.7211 | 0.0000 | 46.0345 | 286758 | 46.0345 | 0.0000 | OTHER | 0.0000 | | 1D0BA376E273B9D622641124D8C59264 | 1774.5924 | 0.0049 | 0.0000 | 1737.4885 | 5081 | 1737.4885 | 0.0000 | OTHER | 0.0000 | | 64CF75576816DB5614F3D5B1F35B1472 | 1801.8767 | 747.0343 | 0.0000 | 827.1674 | 10340 | 827.1674 | 0.0000 | OTHER | 0.0000 | | 23D1C653347BA469396896AD9B20DCA1 | 5564.9419 | 0.0000 | 0.0000 | 5478.2228 | 1257 | 5478.2228 | 0.0000 | OTHER | 0.0000 | | FA4F493FA5CE2DCC64F51CF3754F96C6 | 2478.3956 | 378.7557 | 3.1040 | 1731.1802 | 3357 | 1731.1802 | 0.0000 | OTHER | 0.0000 | +----------------------------------+-------------------+-----------------+------------------+---------------+--------+--------------+---------------+------------+----------------+ 10 rows in set (1.34 sec)説明
- テナントのジッター現象が発生すると、一般的に「テナントCPUが飽和」および「すべてのSQL RTが急増」という現象が見られます。この場合、まずSQL RTの急増が第一現場であるかどうかを判断する必要があります(SQL自体の問題によるRTの急増か、それとも他の問題によるSQL RTの急増か)。
- 上記のSQLは非常に強力なツールであり、
SQL_IDに基づいて集計し、リソース使用量で降順にソート(リソース使用量はavg_exec_time * cntと見なすことができます)して、上位のいくつかのSQLに明らかな異常がないかどうかを観察し、それによって第一現場であるかどうかを判断します。