パラレル実行は、深く複雑なテーマであり、並行操作の仕組みを正確に理解し、パラレル実行の能力をより大きく発揮するためには、一定の学習段階を経る必要があります。初心者がパラレル実行の要点を迅速に習得できるよう、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スペックの下限を表します。各Server上でのパラレルクエリキュー条件の詳細な設定については、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に設定します。