このトピックでは、パフォーマンスを最適化するための AnalyticDB for MySQL テーブルのスキーマ設計方法について説明します。スキーマには、テーブルタイプ、分散キー、パーティションキー、プライマリキー、クラスター化インデックスキーが含まれます。
テーブルタイプの選択
AnalyticDB for MySQL は、レプリケートテーブルと標準テーブルをサポートしています。テーブルタイプを選択する際は、以下の点を考慮してください。
-
レプリケートテーブルは、クラスターの各ノードにデータのレプリカを保存します。各レプリケートテーブルのデータ量は、最大 20,000 行に制限することを推奨します。
-
標準テーブル (パーティションテーブルとも呼ばれます) は、分散システムのクエリ機能を使用してクエリパフォーマンスを向上させることができます。標準テーブルは、数千万行から数千億行まで、大量のデータを保存できます。
分散キーの選択
増分データをインポートするには、標準テーブルを作成する際に分散キーとパーティションキーを指定します。これにより、増分データの同期が可能になります。テーブルを作成する際は、DISTRIBUTED BY HASH(column_name,...) 句を使用して分散キーを指定します。その後、テーブルは column_name フィールドのハッシュ値に基づいてシャーディングされます。詳細については、「CREATE TABLE」をご参照ください。
-
構文
DISTRIBUTED BY HASH(column_name,...) -
使用上の注意
-
トランザクション ID、デバイス ID、ユーザー ID、自動インクリメント列など、値が均等に分散されるフィールドを分散キーとして選択してください。
説明DATE、TIME、TIMESTAMP 型のフィールドは分散キーとして選択しないでください。これらのフィールドは、データ書き込み時にデータスキューを引き起こし、書き込みパフォーマンスを低下させる可能性があります。ほとんどのクエリは、過去 1 日や 1 か月といった時間範囲に限定されます。この場合、クエリ対象のデータは単一のノードにのみ存在する可能性があります。これにより、分散データベースのすべてのノードの処理能力を活用できなくなります。DATE または TIME 型のフィールドは、サブパーティションキーとして使用することを推奨します。詳細については、「パーティションキーの選択」をご参照ください。
-
データシャッフルを削減するために、テーブルの結合に使用されるフィールドを分散キーとして選択してください。たとえば、顧客別に過去の注文を照会する場合は、
customer_idフィールドを分散キーとして選択できます。 -
クエリ条件に頻繁に出現するフィールドを分散キーとして選択してください。これにより、分散キーに基づいたパーティションプルーニングが可能になります。
-
各テーブルは 1 つの分散キーのみを持つことができます。分散キーは 1 つ以上のフィールドを含めることができます。さまざまな複雑なクエリに対応できるよう、分散キーのフィールド数はできるだけ少なくすることを推奨します。
-
テーブル作成時に分散キーを指定しない場合、システムは以下のように処理します。
-
テーブルにプライマリキーがある場合、AnalyticDB for MySQL はプライマリキーをデフォルトの分散キーとして使用します。
-
テーブルにプライマリキーがない場合、AnalyticDB for MySQL は
__adb_auto_id__フィールドを追加し、それをプライマリキーおよび分散キーとして使用します。
-
-
パーティションキーの選択
分散キーを指定した後、単一のシャードに大量のデータが含まれる場合は、パーティションキーを使用してシャードをさらにパーティション化できます。また、クエリステートメントの WHERE 句にサブパーティションフィールドのフィルター条件を含めることで、パーティションプルーニングをトリガーし、スキャンするデータ量を大幅に削減してデータアクセスパフォーマンスを向上させることができます。テーブルを作成する際は、PARTITION BY 句を使用してサブパーティションを定義します。その後、データは指定されたとおりに分割されます。詳細については、「CREATE TABLE」をご参照ください。
-
構文
-
column_nameフィールドの値を使用してテーブルをパーティション化します。構文は次のとおりです。PARTITION BY VALUE(column_name) -
column_nameフィールドの値を%Y%m%d日付形式 (20210101など) に変換してテーブルをパーティション化します。構文は次のとおりです。PARTITION BY VALUE{(DATE_FORMAT(column_name, '%Y%m%d'))|(FROM_UNIXTIME(column_name, '%Y%m%d'))} -
column_nameフィールドの値を%Y%m日付形式 (202101など) に変換してテーブルをパーティション化します。構文は次のとおりです。PARTITION BY VALUE{(DATE_FORMAT(column_name, '%Y%m'))|(FROM_UNIXTIME(column_name, '%Y%m'))} -
column_nameフィールドの値を%Y日付形式 (2021など) に変換してテーブルをパーティション化します。構文は次のとおりです。PARTITION BY VALUE{(DATE_FORMAT(column_name, '%Y'))|(FROM_UNIXTIME(column_name, '%Y'))}
-
-
使用上の注意
-
テーブルに大量のデータが含まれる場合、サブパーティションの選択は非常に重要です。テーブルにサブパーティションがない場合、またはサブパーティションが適切に分割されていない場合、AnalyticDB for MySQL クラスターのパフォーマンスに深刻な影響を与える可能性があります。パーティションフィールドの適合性を診断する方法については、「分散フィールドの妥当性診断」をご参照ください。
-
現在、パーティション分割は年、月、日、または元の値によってのみサポートされています。パーティション分割の粒度が大きすぎたり小さすぎたりすると、クエリおよび書き込みパフォーマンスに影響し、AnalyticDB for MySQL クラスターの安定性にも影響を与える可能性があります。
-
サブパーティションは可能な限り静的な状態に保つことを推奨します。サブパーティションを頻繁に更新することは推奨しません。たとえば、複数の履歴サブパーティションが毎日頻繁に更新されるシナリオがある場合は、使用されているサブパーティションフィールドが適切かどうかを検討してください。
-
LIFECYCLE Nキーワードを使用してテーブルのライフサイクルを管理できます。パーティションはソートされ、Nを超えるパーティションはフィルタリングされます。重要各テーブルでサポートされるパーティションの最大数には制限があります。したがって、パーティションテーブル内のデータを永続的に保持することはできません。パーティション制限の詳細については、「制限事項」をご参照ください。
パーティション数が上限を超えているというエラーが発生し、構成によって制限を調整できない場合は、サブパーティションの粒度を大きくする (たとえば、日単位から月単位のパーティション分割に変更する) か、パーティションキーの設計を最適化してパーティションの総数を削減してください。
-
プライマリキーの選択
プライマリキーは、各レコードの一意の識別子として機能します。テーブルを作成する際は、PRIMARY KEY 句を使用してプライマリキーを定義できます。詳細については、「CREATE TABLE」をご参照ください。
-
構文
PRIMARY KEY (column_name,...) -
使用上の注意
-
プライマリキーを持つテーブルのみが、DELETE や UPDATE などのデータ更新操作をサポートします。
-
AnalyticDB for MySQL テーブルのプライマリキーは、単一のフィールドまたは複数のフィールドの組み合わせにすることができます。より優れたテーブルパフォーマンスを実現するために、数値フィールドをプライマリキーとして使用し、できるだけ少ないフィールドを使用することを推奨します。
-
プライマリキーには、分散キーとパーティションキーを含める必要があります。複合プライマリキーの先頭に分散キーとパーティションキーを配置することを推奨します。分散キーはシャード間でのデータの分散方法を決定し、パーティションキーはシャード内で値の範囲によってデータを分割します。プライマリキーに両方が含まれている場合、クエリオプティマイザーはプライマリキーインデックスを使用して、対応するシャードとパーティション内のデータを特定できるため、クエリパフォーマンスが保証されます。
-
クラスター化インデックスキーの選択
クラスター化インデックスのキー値の論理的な順序により、テーブル内の対応する行の物理的な順序が決まります。クラスター化インデックスキーを選択する際は、以下の点を考慮してください。
-
各テーブルは 1 つのクラスター化インデックスのみをサポートします。作成方法については、「CREATE TABLE」をご参照ください。
-
クエリに常に含まれるフィールドをクラスター化インデックスキーとして使用してください。たとえば、学校の学生情報システムでは、各学生は自分の最終成績のみを表示する必要があります。この場合、学生 ID をクラスター化インデックスとして定義することで、データの局所性を確保し、クエリパフォーマンスを向上させることができます。
-
クラスター化インデックスはテーブル全体をソートするため、CPU リソースなどのリソースを消費します。クラスター化インデックスは慎重に使用してください。
-
クエリに DESC ソートが含まれる場合、CREATE TABLE ステートメントで
CLUSTERED KEY (col1 DESC, col2 DESC)構文を使用することで、対応するフィールドの DESC ソートを効率的にサポートし、クエリ実行時の追加のソートオーバーヘッドを削減できます。
例
以下の要件を満たす customer という名前のテーブルを作成します。
-
顧客のログイン時刻 (
login_time列) に基づいてテーブルデータをパーティション化し、ログイン時刻を%Y%m%d日付形式に変換します。 -
最後の 30 パーティションのデータのみを保持します (ライフサイクルは 30) 。
-
顧客 ID (
customer_id列) に基づいてデータを分散します。 -
login_time, customer_id, phone_numを複合プライマリキーとして設定します。
CREATE TABLE ステートメントは次のとおりです:
CREATE TABLE customer (
customer_id bigint NOT NULL COMMENT '顧客 ID',
customer_name varchar NOT NULL COMMENT '顧客名',
phone_num bigint NOT NULL COMMENT '電話番号',
city_name varchar NOT NULL COMMENT '都市',
sex int NOT NULL COMMENT '性別',
id_number varchar NOT NULL COMMENT 'ID カード番号',
home_address varchar NOT NULL COMMENT '自宅住所',
office_address varchar NOT NULL COMMENT 'オフィス住所',
age int NOT NULL COMMENT '年齢',
login_time timestamp NOT NULL COMMENT 'ログイン時刻',
PRIMARY KEY (login_time, customer_id, phone_num)
)
DISTRIBUTED BY HASH(customer_id)
PARTITION BY VALUE(DATE_FORMAT(login_time, '%Y%m%d')) LIFECYCLE 30
COMMENT '顧客情報テーブル';
よくある質問
-
Q: サブパーティションを作成した後、テーブルのすべてのサブパーティションとその統計情報を表示するにはどうすればよいですか?
A: 次の SQL ステートメントを実行して、テーブルのすべてのサブパーティションとその統計情報を表示できます:
SELECT partition_id, -- パーティション名 row_count, -- パーティション内の総行数 local_data_size, -- パーティションのローカルストレージサイズ index_size, -- パーティションのインデックスサイズ pk_size, -- パーティションのプライマリキーインデックスサイズ remote_data_size -- パーティションのリモートストレージサイズ FROM information_schema.kepler_partitions WHERE schema_name = '$DB' AND table_name ='$TABLE' AND partition_id > 0;重要コンパクションがトリガーされていない増分データのパーティションは表示されません。すべてのサブパーティションのリアルタイムリストを表示するには、
select distinct $partition_column from $db.$table;ステートメントを実行してください。 -
Q: シャード数に影響する要因は何ですか? シャード数を自分で変更できますか?
A: シャード数は、クラスターの作成時に初期仕様に基づいて自動的に計算されます。シャード数を変更することはできません。
-
Q: クラスター仕様の変更はシャード数に影響しますか?
A: クラスターのアップグレードまたはダウングレードは、シャード数に影響しません。
-
Q: AnalyticDB for MySQL は分散キーまたはパーティションキーの変更をサポートしていますか?
A: いいえ、サポートしていません。これらのキーを変更するには、テーブルの再作成などが必要になります。詳細については、「ALTER TABLE」をご参照ください。
-
Q: 同じテーブルグループ内のテーブルが満たす必要がある一貫性要件は何ですか?
A: AnalyticDB for MySQL では、同じテーブルグループ内のすべてのテーブルは、同じ数のプライマリハッシュパーティション、セカンダリリストパーティション、レプリカを持つ必要があります。そうでない場合、テーブルを同じテーブルグループに追加することはできません。