パーティションバランスとは
MySQL NDB Cluster 7.5より導入された、今までよりも柔軟なパーティショニングを
提供する機能です。
マニュアルでは下記のページで説明されています。
MySQL NDB Clusterのパーティションについて
MySQL NDB Clusterでは、追加されたデータは自動的に各データノードの
パーティショニングされた表に格納されます。
デフォルトは主キーによるKEYパーティショニングです。
データは以下の条件で各パーティションへ分配されます。
1 |
partiton = MOD(MD5(<primary key value>),<partition count>) |
パーティションはLDMスレッドと密接な関係にあり、パーティション数はLDMスレッド数
によって決定されます。
LDMスレッドとは、データノードのローカルデータを管理するためのスレッドです。
ver7.4 以前では、以下のパーティション方式のみ提供されていました。
- 各ノードの各LDMスレッドごとに1つのパーティションが作成される。
- NoOfReplicas(デフォルト2)によってLDMスレッドが担当するパーティションはプライマリレプリカ、バックアップレプリカの2つ。
- 読み取りはプライマリレプリカを使用。
LDMスレッド数は、ndbmtdをご利用の場合MaxNoOfExecutionThreads、もしくはThreadConfig
パラメータによって決定されます。
詳しくは以下のマニュアルをご確認ください。
MaxNoOfExecutionThreads
ThreadConfig
パーティションバランスを指定したテーブル作成
パーティションバランスはCREATE TABLE時に指定します。
1 |
mysql> CREATE TABLE (.....) ENGINE=ndbcluster COMMENT='NDB_TABLE=PARTITION_BALANCE=FOR_RA_BY_LDM'; |
指定するパラメータの命名規則は以下の通りです。
1 2 3 4 5 6 7 8 9 |
FOR_<読み取りオプション名>_BY_<配布方式> < 読み取りオプション名 > RP : Read Primary RA : Read Any <配布方式> LDM: LDM Thread Count NODE: NODE Count |
選択可能なパーティションバランスの方式
データノード数 4、レプリカ数 2(つまり2ノードのノードグループが2つ)存在している
ケースを前提として説明します。
FOR_RP_BY_LDM
7.4以前、及びデフォルトで選択される方式です。
各ノードの各LDMスレッドごとに1つのパーティションをプライマリ、バックアップに作成します。
読み取りはプライマリレプリカから実行されます。
FOR_RA_BY_LDM
各ノードの各LDMスレッドごとに1つのパーティションをプライマリ、バックアップに作成します。
いずれかのレプリカから読み取りを行うことができます。
LDMスレッドは読み取りを行うパーティションにつき1スレッドとなるため、パーティション数は
RPに比較して半分となります。
FOR_RP_BY_NODE
ノードごとに1つのパーティションをプライマリ、バックアップに作成します。
読み取りはプライマリレプリカから実行されます。
FOR_RA_BY_NODE
各ノードに単一のパーティションを持ちます。
つまり、各ノードには1つのプライマリレプリカかバックアップレプリカがあり、
自身のプライマリレプリカを持たないノードが発生します。
読み取りは任意のレプリカから行うことができます。
実際に作成してパーティションを確認
config.iniは以下の通りです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
[mgm] NodeID = 101 HostName = mgm1 Datadir = /var/lib/mysql-cluster [ndbd default] DataMemory = 512M IndexMemory = 128M Datadir = /var/lib/mysql-cluster ThreadConfig=ldm{count=8} NoOfFragmentLogParts=8 [ndbd] NodeID = 1 HostName = data11 [ndbd] NodeID = 2 HostName = data12 [ndbd] NodeID = 3 HostName = data21 [ndbd] NodeID = 4 HostName = data22 [api] |
今回、データノード数は4、NoOfReplicasはデフォルトの2であるため、
2ノードずつのノードグループが2つ作成されています。
また、検証のためにLDMスレッドを8スレッドとしています。
パーティショニングの状況は、ndb_descコマンドを使用して確認できます。
FOR_RP_BY_LDMのテーブルから確認してみます。
1 2 3 4 5 6 7 8 |
CREATE TABLE `sbtest1` ( `id` int(11) NOT NULL AUTO_INCREMENT, `k` int(11) NOT NULL DEFAULT '0', `c` char(120) NOT NULL DEFAULT '', `pad` char(60) NOT NULL DEFAULT '', PRIMARY KEY (`id`), KEY `k_1` (`k`) ) ENGINE=ndbcluster COMMENT='NDB_TABLE=PARTITION_BALANCE=FOR_RP_BY_LDM' |
- ndb_desc結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
$ ndb_desc -c narita-ndb-mgm-1:1186 -bnp -d test sbtest1 ・・・略 PartitionCount: 32 FragmentCount: 32 PartitionBalance: FOR_RP_BY_LDM ・・・略 -- Per partition info for sbtest1 -- Partition Row count -略- Frag fixed memory -略- Nodes 0 346 ---- 98304 ---- 1,2 1 279 ---- 65536 ---- 3,4 2 315 ---- 98304 ---- 2,1 3 299 ---- 65536 ---- 4,3 4 310 ---- 98304 ---- 1,2 5 322 ---- 98304 ---- 3,4 6 319 ---- 98304 ---- 2,1 7 301 ---- 65536 ---- 4,3 8 325 ---- 98304 ---- 1,2 9 301 ---- 65536 ---- 3,4 10 322 ---- 98304 ---- 2,1 11 317 ---- 98304 ---- 4,3 12 309 ---- 98304 ---- 1,2 13 288 ---- 65536 ---- 3,4 14 305 ---- 65536 ---- 2,1 15 328 ---- 98304 ---- 4,3 16 341 ---- 98304 ---- 2,1 17 319 ---- 98304 ---- 4,3 18 310 ---- 98304 ---- 1,2 19 306 ---- 65536 ---- 3,4 20 334 ---- 98304 ---- 2,1 21 307 ---- 98304 ---- 4,3 22 321 ---- 98304 ---- 1,2 23 315 ---- 98304 ---- 3,4 24 295 ---- 65536 ---- 2,1 25 306 ---- 65536 ---- 4,3 26 326 ---- 98304 ---- 1,2 27 330 ---- 98304 ---- 3,4 28 298 ---- 65536 ---- 2,1 29 284 ---- 65536 ---- 4,3 30 304 ---- 65536 ---- 1,2 31 318 ---- 98304 ---- 3,4 |
パーティション数と、バランシングのタイプが確認できました。
FOR_RP_BY_LDMは、MySQL NDB Clusterのデフォルトであり、基本的にこの方式を使用すれば問題ありません。
各LDMスレッドに1:1でパーティションが存在するため、今回の設定では8*4=32パーティション存在しています。
各パーティションのデータに均等にアクセスするようなワークロードでは最も各LDMスレッドの負荷が均一です。
ノード1,2が所属するノードグループ1を例に取ると、各ノードのプライマリレプリカは以下のように所属しています。
1 2 |
Node1 : 0,4, 8,12,18,22,26,30 Node2 : 2,6,10,14,16,20,24,28 |
クエリが実行された際には、実行ノードがプライマリレプリカを持たないパーティションのデータは対向ノードに要求します。
それでは、FOR_RA_BY_LDMにした時はどうでしょうか。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
-- Per partition info for sbtest1 -- Partition Row count -略- Frag fixed memory -略- Nodes 0 687 ---- 163840 ---- 2,1 1 598 ---- 131072 ---- 4,3 2 625 ---- 163840 ---- 1,2 3 605 ---- 131072 ---- 3,4 4 644 ---- 163840 ---- 2,1 5 629 ---- 163840 ---- 4,3 6 640 ---- 163840 ---- 1,2 7 616 ---- 163840 ---- 3,4 8 620 ---- 163840 ---- 2,1 9 607 ---- 131072 ---- 4,3 10 648 ---- 163840 ---- 1,2 11 647 ---- 163840 ---- 3,4 12 607 ---- 131072 ---- 2,1 13 572 ---- 131072 ---- 4,3 14 609 ---- 131072 ---- 1,2 15 646 ---- 163840 ---- 3,4 |
パーティション数が半分になっていますが、バックアップレプリカからも読み取り可能な方式です。
RPの際にはノードグループ1に所属するパーティションが更に2分割されてノード1、2が所有していましたが、ノードグループに所属するノードは自身のノードグループ全体のパーティションを読み取れるようになっています。
ただし、バックアップレプリカに対しても完全な同期が必要となるため、WRITE系の処理のパフォーマンスは落ちます。
LDMスレッドの半数がフリーとなるため、あるパーティションに対する負荷が高まった場合も、他のLDMスレッドが動作することができます。
FOR_RP_BY_NODEとした場合は以下です。
1 2 3 4 5 6 |
-- Per partition info for sbtest1 -- Partition Row count -略- Frag fixed memory -略- Nodes 0 2558 ---- 557056 ---- 2,1 1 2406 ---- 524288 ---- 4,3 2 2522 ---- 557056 ---- 1,2 3 2514 ---- 557056 ---- 3,4 |
パーティションがノード数と等価になり、1つのパーティションに対して、複数のLDMスレッドが動作できるようになりました。
ただし、パーティション数が減るとレンジスキャンする範囲が広くなってしまい、パフォーマンスの劣化につながる場合もあります。
この方式は、マスタ表のような基本的に少ない行から構成される表で有効です。
FOR_RA_BY_NODEとすると、以下です。
1 2 3 4 |
-- Per partition info for sbtest1 -- Partition Row count -略- Frag fixed memory -略- Nodes 0 5080 ---- 1114112 ---- 2,1 1 4920 ---- 1081344 ---- 4,3 |
FOR_RA_BY_LDMの場合と同様に、ノードグループ単位でパーティションが作成されました。
用途としては、FOR_RP_BY_NODEの場合と同一ですが、加えてノード間通信を少なくすることができます。
なお、ver7.5.4からは、FOR_RA_BY_LDM_X_2、FOR_RA_BY_LDM_X_3、FOR_RA_BY_LDM_X_4という方式が追加されており、
LDMごとに、方式名の末尾の数値のパーティションを作成する事ができるようになりました。
表のワークロードに合わせて設定を検討するとよいかと思います。
以上となります。
MySQL NDB Clusterのパーティションの理解にお役立て頂ければ幸いです。