テーブルスキーマ設計の最適化
概要
Schemaの設計とチューニングにおいて、テーブルSchemaの設計は重要な部分であり、テーブルエンジンの選択、パーティションとバケットカラムの選択、パーティションとバケットサイズの設定、キーカラムとフィールドタイプの最適化などが含まれます。適切なSchema設計が不足しているシステムでは、データスキューなどの問題が発生し、システムの並列性とソート機能を十分に活用できず、Dorisシステムがビジネスシステムにおいてその真の性能優位性を実現することを妨げる可能性があります。
詳細な設計原則については、Data table Designセクションで詳しい情報をご確認いただけます。本章では、実際のケースの観点から、いくつかの典型的なシナリオにおけるSchema設計の問題によって引き起こされる性能ボトルネックを紹介し、ビジネスチューニングの参考として最適化の提案を提供します。
ケース1: テーブルエンジンの選択
DorisはDuplicate、Unique、Aggregateの3つのテーブルモデルをサポートしています。その中で、UniqueはMerge-On-Read (MOR)とMerge-On-Write (MOW)にさらに分類できます。
これらのテーブルモデルのクエリ性能は、優れている順に:Duplicate > MOW > MOR == Aggregateです。したがって、通常の状況では、特別な要件がない場合、より良いクエリ性能のためにDuplicateテーブルが推奨されます。
ビジネスでデータ更新の要件がなく、クエリ性能に対する要求が高い場合、Duplicate tableが推奨されます。
ケース2: バケットカラムの選択
Dorisはデータのバケット化をサポートしており、これはSchemaのバケットキーに基づいてデータを分散し、データバケットを形成することを意味します。
適切なバケットカラムの選択は、生データの合理的な分散にとって重要であり、データスキューによって引き起こされる性能問題を効果的に防ぎます。同時に、DorisのColocate Joinとバケット Shuffle Join機能の活用を最大化し、Join操作の性能を大幅に向上させます。
テーブルt1のテーブル作成文を例にとると、現在のバケットカラムはc2に設定されています。しかし、実際のデータインポート処理中に、カラムc2のすべての値がnullにデフォルト設定されている場合、64個のバケットが設定されていても、1つのバケットのみがすべてのデータを含むことになります。この極端なケースは深刻なデータスキューを引き起こし、性能ボトルネックをもたらします。
CREATE TABLE `t1` (
`c1` INT NULL,
`c2` INT NULL
) ENGINE=OLAP
DUPLICATE KEY(`c1`)
DISTRIBUTED BY HASH(`c2`) BUCKETS 64
PROPERTIES (
"replication_allocation" = "tag.location.default: 1"
);
insert into t1 select number, null from numbers ('number'='10000000');
上記の状況に対応するため、bucket列をc2からc1に変更することで、適切なデータハッシュを実現し、システムの並列処理能力を最大化して、チューニング目的を達成できます。
したがって、Schema設計フェーズでは、ビジネス担当者がビジネス特性に基づいて事前に適切なbucket列を設計する必要があります。例えば、列c2のビジネス的意味がnullや特定の値など、大量の偏った値を含む可能性があることが事前に分かっている場合、これらのフィールドをbucket列として避けるべきです。逆に、ユーザIDなど、ビジネス的意味において適切なハッシュ特性を持つフィールドをbucket列として選択すべきです。パフォーマンス問題のトラブルシューティングフェーズでは、以下のSQL文を使用してbucketフィールドにデータスキューがあるかを確認し、それに応じて後続の最適化調整を行うことができます。
select c2,count(*) cnt from t1 group by c2 order by cnt desc limit 10;
bucket列にデータスキュー問題があるかどうかを確認してください。もしそうであれば、ビジネス的な意味で適切なハッシュ特性を持つフィールドでbucket列を置き換えてください。
適切な事前設計により、問題が発生した際の特定と修正のコストを大幅に削減できることは明らかです。したがって、不要なコストの発生を避けるために、ビジネス担当者がSchema設計段階で厳密な設計と確認を実施することを強く推奨します。
ケース3: Key Column最適化
3つのテーブルモデルのうち、テーブル作成SchemaでDuplicate Key、Unique Key、またはAggregate Keyが明示的に指定されている場合、DorisはストレージレベルでKey列に基づいてデータがソートされることを保証します。この機能は、データクエリパフォーマンス最適化のための新しいアイデアを提供します。具体的には、Schema設計段階において、ビジネスクエリで等価クエリや範囲クエリに頻繁に使用される列をKey列として定義できる場合、そのようなクエリの実行速度が大幅に向上し、全体的なパフォーマンスが向上します。
以下は、ビジネスクエリ要件の例です:
select * from t1 where t1.c1 = 1;
select * from t1 where t1.c1 > 1 and t1.c1 < 10;
select * from t1 where t1.c1 in (1, 2, 3);
上記のビジネス要件とテーブルt1のSchema設計および後の最適化において、クエリプロセスを高速化するためにカラムc1をKeyカラムとして設定することを検討することが推奨されます。以下に例を示します:
CREATE TABLE `t1` (
`c1` INT NULL,
`c2` INT NULL
) ENGINE=OLAP
DUPLICATE KEY(`c1`)
DISTRIBUTED BY HASH(`c2`) BUCKETS 10
PROPERTIES (
"replication_allocation" = "tag.location.default: 1"
);
ビジネスクエリで頻繁に使用されるカラムをキーカラムとして設定することで、クエリプロセスを高速化できます。
ケース4: フィールドタイプの最適化
データベースシステムにおいて、異なるタイプのデータを処理する際の複雑さは大きく異なります。例えば、可変長タイプの処理は固定長タイプよりもはるかに複雑であり、同様に、高精度タイプの処理は低精度タイプよりも複雑です。
この特性は、ビジネスシステムSchemaの設計と後の最適化において重要な洞察を提供します:
- ビジネスシステムの表現と計算のニーズを満たしながら、固定長タイプを優先し、可変長タイプの使用を避けるべきです;
- 同時に、高精度タイプの代わりに低精度タイプを採用すべきです。具体的な実践には、VARCHARまたはSTRINGタイプのフィールドをBIGINTに置き換える、DECIMALタイプのフィールドをFLOAT / INT / BIGINTに置き換えるなどが含まれます。このようなフィールドタイプの合理的な設計と最適化により、ビジネス計算効率が大幅に向上し、システムパフォーマンスが改善されます。
Schemaタイプを定義する際は、固定長および低精度タイプを優先するという原則に従ってください。
まとめ
まとめると、よく設計されたSchemaはDorisの機能を最大限に活用でき、それによってビジネスパフォーマンスを大幅に向上させることができます。逆に、最適化されていないSchema設計は、データスキューの原因となるなど、ビジネスに全般的な悪影響を与える可能性があります。したがって、初期のSchema設計最適化作業は特に重要です。