パラレル実行は深く複雑なトピックであり、並行操作の仕組みを正確に理解し、その能力を最大限に発揮するには、一定の学習段階を経る必要があります。初心者がパラレル実行の要点を迅速に習得できるように、OceanBaseデータベースV3.1以降では、入門実践ガイドを提供しています。本記事で示すパラメータは最適な選択肢とは限りませんが、ほとんどの不良状態を効果的に回避し、初心者がパラレル実行機能をより容易に適用できるようにします。
環境の初期化
APテナントで設定します:
/* MySQL */
SET GLOBAL parallel_servers_target = MIN_CPU * 20;
/* Oracle */
ALTER SYSTEM SET parallel_servers_target = MIN_CPU * 20;
ここで、MIN_CPU はCPUスペックの下限を表します。各サーバー上のパラレルクエリキューシング条件の詳細については、parallel_servers_targetを参照してください。
統計情報の収集
V3.x系では統計情報の収集はメジャーコンパクションと結びついています。そのため、データをインポートした後、統計情報を確実に収集するには、一度のメジャーコンパクションを開始する必要があります。
V4.x系では、データをインポートした後、DBMS統計情報パッケージを直接呼び出して統計情報を収集できます。
統計情報の詳細については、統計情報の概要を参照してください。
ヒントの設定
各SQLの並列度(DOP)は、物理CPU数の1.5倍を超えないように設定してください。 一般的に、複数のSQLが同時に実行されていない場合、単一のSQLの並列度はCPU数に設定できます。例えば、システムの物理CPU数が32の場合、ヒントは /*+ PARALLEL(32) */ に設定します。
パフォーマンスチューニング
top -Hを実行して、テナントのCPU使用状況を確認します。- 単一SQLのパフォーマンスが期待に達していない場合は、
sql_plan_monitorを使用してパフォーマンスレポートを取得します。
-- open_dt は、オペレーターが Open から Close までの時間間隔を表します。
-- row_dt は、オペレーターが最初の行を出力してから OB_ITER_END を出力するまでの時間間隔を表します。
-- 値が NULL の場合、最初の行を出力したことがないか、OB_ITER_END を出力したことがないことを意味します。
-- スローSQLにHintを追加してください: /*+ monitor */
-- Hintを追加した後のスローSQLを実行すると、Trace_idが得られます。以下の Yxxxxxxxxx に置き換えて、以下のSQLを実行します。
-- MySQLテナント:
-- 集計:
SELECT op_id, op, rows, rescan, threads, (close_time - open_time) open_dt, (last_row_eof_time-first_row_time) row_dt, open_time, close_time, first_row_time, last_row_eof_time FROM
(
select plan_line_id op_id, concat(lpad('', plan_depth, ' '), plan_operation) op, sum(output_rows) rows, sum(STARTS) rescan, min(first_refresh_time) open_time, max(last_refresh_time) close_time, min(first_change_time) first_row_time, max(last_change_time) last_row_eof_time, count(1) threads from oceanbase.gv$sql_plan_monitor where trace_id = 'Yxxxxxxxxx' group by plan_line_id, plan_operation order by plan_line_id
) a;
-- 詳細
SELECT op_id, thread, op, rows, rescan, (close_time - open_time) open_dt, (last_row_eof_time-first_row_time) row_dt, open_time, close_time, first_row_time, last_row_eof_time FROM
(
select plan_line_id op_id, PROCESS_NAME thread, concat(lpad('', plan_depth, ' '), plan_operation) op, output_rows rows, STARTS rescan, first_refresh_time open_time, last_refresh_time close_time, first_change_time first_row_time, last_change_time last_row_eof_time from oceanbase.gv$sql_plan_monitor where trace_id = 'Yxxxxxxxxx' order by plan_line_id, PROCESS_NAME
) a;
-- Oracleテナント:
--説明:open_dt は、オペレーターが Open から Close までの時間間隔を表します。
--説明:row_dt は、オペレーターが最初の行を出力してから OB_ITER_END を出力するまでの時間間隔を表します。
--説明:値が NULL の場合、最初の行を出力したことがないか、OB_ITER_END を出力したことがないことを意味します。
-- 集計
SELECT op_id, op, output_rows, rescan,threads ,(close_time - open_time) open_dt, (last_row_eof_time-first_row_time) row_dt, open_time, close_time, first_row_time, last_row_eof_time FROM
(
select plan_line_id op_id, concat(lpad(' ', max(plan_depth), ' '), plan_operation) op, sum(output_rows) output_rows, sum(STARTS) rescan, min(first_refresh_time) open_time, max(last_refresh_time) close_time, min(first_change_time) first_row_time, max(last_change_time) last_row_eof_time, count(1) threads from sys.gv$sql_plan_monitor where trace_id = 'Yxxxxxxxxx' group by plan_line_id, plan_operation,plan_depth order by plan_line_id
) a;
-- 詳細
SELECT op_id, thread, op, output_rows, rescan, (close_time - open_time) open_dt, (last_row_eof_time-first_row_time) row_dt, open_time, close_time, first_row_time, last_row_eof_time FROM
(
select plan_line_id op_id, PROCESS_NAME thread, concat(lpad(' ', plan_depth, ' '), plan_operation) op, output_rows, STARTS rescan, first_refresh_time open_time, last_refresh_time close_time, first_change_time first_row_time, last_change_time last_row_eof_time from sys.gv$sql_plan_monitor where trace_id = 'Yxxxxxxxxx' order by plan_line_id, process_name
) a;
よくある質問
Queryのパフォーマンスが期待通りにならない、CPUがフルに使われていない?
show variables like 'parallel_servers_targetを実行し、target値がMIN_CPU× 20以上であることを確認してください。PDMLのパフォーマンスが期待通りにならない?
explain extendedを使用してPDMLを説明し、計画がPDMLを経由していることを確認してください。PDMLを経由していない場合、計画の最下部のNoteフィールドにその理由が記載されています。一般的には、変更対象のテーブルにトリガー、外部キー、local unique indexなどが含まれているためです。DISTRIBUTED INSERT、DISTRIBUTED UPDATE、DISTRIBUTED DELETEなどの文字列が表示された場合、PDMLを経由していないことを意味します。PDMLがタイムアウトし、内部ログに
-4138 OB_SNAPSHOT_DISCARDEDエラーが表示される?undo_retentionパラメータをPDMLの最大実行時間以上に設定してください。デフォルト値はわずか30分であり、PDMLの実行時間が30分を超えるとこの問題が発生し、実行が終了してタイムアウトするまで再試行されます。OceanBase V4.1以降ではPDMLタイムアウトの問題は発生しなくなっており、手動で
undo_retentionを設定する必要はありません。業務上の変更が一切できない、業務SQLを並列化する方法は?
OBProxyでは、Webインターフェース上で接続設定を変更し、並列処理を有効にできます。例えば、読み書き分離接続において、すべてのSQLの並列度を2に設定します。