トランザクションのコミット時間はタイプによって異なります。パフォーマンスチューニングでは、マシンをまたがる分散トランザクションの割合をできるだけ低減することが望ましいです。トランザクションモデルの改善は、以下の観点から取り組むことができます:
業務全体のロジック。
具体のトランザクションに細分化する。
複数テーブル・単一テーブルのトランザクションの割合、および各種SQLの実行頻度を把握する。
トランザクションタイプの統計
SQLの実行計画は4種類に分類されます:Local、Remote、Distribute、Uncertainです。そのうち、Localは現在のステートメントに関連するパーティションのリーダーがセッションが存在するマシンと同じであることを示します。Remoteは、現在のステートメントに関連するパーティションのリーダーがセッションが存在するマシンと異なることを示します。DistributeおよびUncertainの計画では、リーダーとセッションの関係を特定できず、同一マシン上にある場合もあれば、複数のマシンにまたがっている場合もあります。
トランザクションのパフォーマンスにおいては、単一マシントランザクションを優先的に使用し、次に分散トランザクションを使用します。実行計画のタイプ統計情報から、分散トランザクションの割合を大まかに推定し、それによってチューニングのためのデータサポートを提供することができます。関連するSQLは以下のとおりです:
MySQL [oceanbase]> select plan_type, count(1) from gv$ob_sql_audit where
request_time > time_to_usec('2021-08-24 18:00:00') group by plan_type;
+-----------+----------+
| plan_type | count(1) |
+-----------+----------+
| 1 | 17119 |
| 0 | 9614 |
| 3 | 4400 |
| 2 | 23429 |
+-----------+----------+
4 rows in set
ここで、plan_type = 1、2、3はそれぞれLocal、Remote、Distributeの実行計画を表します。一般的に、0はplanのないSQLステートメントを表します。例えば、set autocommit=0/1、commitなどが該当します。
非ローカルプランの分析
非ローカルプランのリクエスト(plan_type = 0 を除く)は、ほとんどの場合、トランザクションがマシン間で横断することになり、単一マシントランザクションに比べてパフォーマンスに一定の影響を与えます。以下のいずれかの状況に従って確認できます:
プライマリゾーンが単一ゾーン & 単一ユニット。
プライマリゾーンが単一ゾーン & 複数ユニット。
プライマリゾーンがRANDOM。
プライマリゾーンが単一ゾーン&単一ユニットの場合
単一ユニットでデプロイされたシナリオでRemoteやUncertainな実行計画が発生した場合、それは想定外のことです。その原因はおおよそ以下のいくつかの点にあります:
当該テナントのフォロワーに直接接続しています。実行計画のタイプ統計情報を確認することで確認できます。
アプリケーションはOBProxyに接続していますが、トランザクションの最初のSQLがOBProxyによって正しく転送されず、結果としてセッションとトランザクションに関連するパーティションのリーダーが異なるマシンにまたがってしまいます。この場合、クラスタ内のすべてのOBProxyのログを確認する必要があります。重要なログ情報は以下の通りです:
fail to caculate partition id, just use tenant server一部のパーティションがちょうどリーダー切り替えを行ったばかりで、OBServerまたはOBProxyが維持するLocation Cacheがまだ最新に更新されていません。
状況1の場合は、アプリケーションを変更してOBProxyに接続させる必要があります。状況2の場合は、現在のSQLが複雑すぎて、OBProxyがParser処理中にアクセスが必要なパーティションを計算できず、そのためランダムに送信していることを意味します。この場合はSQLの書き方を調整し、パーティションキーを含める必要があります。状況3の場合は、処理は不要です。
プライマリゾーンが単一ゾーン & 複数ユニットの場合
このシナリオでは、同一ゾーン内のOBServer間で自動的にパーティションのロードバランシングが行われ、トランザクションのマシントランザクションはおおむね可能です。マシントランザクションを回避するため、トランザクション内のステートメント実行状況を踏まえてTable Groupを分割し、トランザクションを可能な限り単一マシンで実行できるようにします。
Table Groupの使用方法は以下のとおりです:
--非パーティションシナリオ
create tablegroup tg1;
create table t1 (id1 int, id2 int) tablegroup tg1;
create table t2 (id1 int, id2 int) tablegroup tg1;
--HASHパーティション(MySQLモード)
create tablegroup tg2 partition by hash partitions 2;
create table pg_trans_test2_1(id1 int, id2 int)
tablegroup tg2 partition by hash(id1 % 2) partitions 2;
create table pg_trans_test2_2(id1 int, id2 int)
tablegroup tg2 partition by hash(id1 % 2) partitions 2;
--HASHパーティション(Oracleモード)
create tablegroup tg2 partition by hash partitions 2;
create table pg_trans_test2_1(id1 int, id2 int)
tablegroup tg2 partition by hash(id1) partitions 2;
create table pg_trans_test2_2(id1 int, id2 int)
tablegroup tg2 partition by hash(id1) partitions 2;
--RANGEパーティション(MySQLモード)
create tablegroup tg3
partition by range columns 1 (
partition p0 values less than (10),
partition p1 values less than(20));
create table pg_trans_test3_1(id1 int, id2 int) tablegroup tg3
partition by range columns(id1)
(partition p0 values less than (10),
partition p1 values less than(20));
create table pg_trans_test3_2(id1 int, id2 int) tablegroup tg3
partition by range columns(id1)
(partition p0 values less than (10),
partition p1 values less than(20));
--RANGEパーティション(Oracleモード)
create tablegroup tg3
partition by range columns 1
(partition p0 values less than (10),
partition p1 values less than(20));
create table pg_trans_test3_1(id1 int, id2 int)
tablegroup tg3 partition by range (id1)
(partition p0 values less than (10),
partition p1 values less than(20));
create table pg_trans_test3_2(id1 int, id2 int)
tablegroup tg3 partition by range (id1)
(partition p0 values less than (10),
partition p1 values less than(20));
--LISTパーティション(MySQLモード)
create tablegroup tg4 partition by list columns 1 (
partition p0 values in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
partition p1 values in (11, 12, 13, 14, 15, 16, 17, 18, 19, 20)
);
create table pg_trans_test4_1(id1 int, id2 int) tablegroup tg4 partition by list columns(id1) (
partition p0 values in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
partition p1 values in (11, 12, 13, 14, 15, 16, 17, 18, 19, 20)
);
create table pg_trans_test4_2(id1 int, id2 int) tablegroup tg4 partition by list columns(id1) (
partition p0 values in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
partition p1 values in (11, 12, 13, 14, 15, 16, 17, 18, 19, 20)
);
--LISTパーティション(Oracleモード)
create tablegroup tg4 partition by list columns 1 (
partition p0 values (1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
partition p1 values (11, 12, 13, 14, 15, 16, 17, 18, 19, 20)
);
create table pg_trans_test4_1(id1 int, id2 int) tablegroup tg4 partition by list(id1) (
partition p0 values (1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
partition p1 values (11, 12, 13, 14, 15, 16, 17, 18, 19, 20)
);
create table pg_trans_test4_2(id1 int, id2 int) tablegroup tg4 partition by list(id1) (
partition p0 values (1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
partition p1 values (11, 12, 13, 14, 15, 16, 17, 18, 19, 20)
);
Primary ZoneがRANDOMの場合
RANDOMデプロイメントでは、そのテナントのテーブルリーダーがランダムに分散し、分散クロスマシントランザクションも同様に高い確率で発生します。
トランザクションコミットの最適化プラン
シングルテーブル & マルチテーブルの単一マシントランザクション
OceanBaseデータベースV4.0バージョンでは、シングルログストリームアーキテクチャの調整により、トランザクションが関連するログストリームのリーダーが同一マシン上にある場合、デフォルトでシングルログストリームトランザクションを経由します。このトランザクションモデルはパフォーマンスが最も高いため、設定項目の調整は不要です。
クロスマシントランザクション
主に以下の2つの問題を解決します:
マルチマシン機能を可能な限り活用する。
OBServerのトラフィックロードバランシング。
具体的な手法:
クロスマシントランザクションを回避するため、トランザクション内のステートメント実行状況を踏まえてTable Groupを分割し、トランザクションが単一マシンで実行されるようにします。詳細については、プライマリゾーンが単一ゾーン & 複数ユニットを参照してください。
バッチインポートのシナリオでは、PDML並列実行機能(3.2以降のバージョン)を可能な限り活用します。
ロード状況に応じてネットワークスレッド数(
net_thread_count)を調整します。この構成パラメータはデフォルトで0に設定されており、プロセス起動後、現在のマシンのCPUコア数に基づいて、そのマシンで必要な数を自動的に計算します。計算式は以下のとおりです:min( 6, cpu_core/8 )。実際の状況に応じて期待値を手動で調整し、プロセスを再起動することで変更が有効になります。
注意事項
V2.2.x及びそれ以前のバージョンでは、1段階コミットの最適化を有効にすることはできません。
V3.2.x及びそれ以前のバージョンでは、本番環境でのPartition Group最適化の使用は推奨されません。パフォーマンスチューニングによりパフォーマンスが向上します。