YYYYWEEK は、DATE、DATETIME、または TIMESTAMP 型の列の日付に基づき、ISO 年週番号(ISO week number)と年を用いて、データをデータベースシャードおよびテーブルシャードに分割します。
仕組み
YYYYWEEK は、シャードキーの値から年と ISO 年週番号を抽出し、(年 × 54 + ISO_年週番号) % D を計算します。ここで、D はデータベースシャード数です。この計算結果により、各行がどのシャードに配置されるかが決定されます。
年度をまたぐ週: ISO 年週番号では、12 月の最終数日が翌年の第 1 週に割り当てられる場合があります。たとえば、2012 年 12 月 31 日は ISO 年週番号で 2013 年の第 1 週に該当するため、YYYYWEEK('2012-12-31 12:12:12') の評価結果は (2013 × 54 + 1) % D となり、(2012 × 54 + 52) % D にはなりません。
サイクル終了後のデータ再利用: 定義されたサイクルが完了した後に同一の週が再出現すると、その週の過去のデータと同じシャードにデータがルーティングされる場合があります。たとえば、2012 年の第 1 週から始まる 2 年間のサイクルの場合、2014 年の第 1 週のデータは、2012 年の第 1 週のデータと同じシャードに配置される可能性があります。具体的なシャードは、テーブルシャード総数によって決まります。
YYYYWEEK の適用範囲
以下のケースで YYYYWEEK を使用します。
クエリで年と週単位でのフィルター処理や集計処理を行う場合 — たとえば、週次売上レポートや週次アクティブユーザー数の集計などです。
データが複数年にわたって存在し、年度をまたぐ週の配置(alignment)が重要となる場合です。
WEEKは毎年週番号をリセットしますが、YYYYWEEKは年情報を保持します。複数年にわたる期間に対して週単位の粒度(granularity)が必要な場合です。月単位の粒度には
YYYYMMを、週単位の粒度にはYYYYWEEKを使用します。
YYYYWEEK を tbpartition by YYYYWEEK(ShardKey) と併用することで、データベースシャードおよびテーブルシャードの両方を同一のキーで分割できます。これにより、パーティションキーを含むクエリに対して直接シャード検索が可能になります。
制限事項
パーティションキーは、DATE、DATETIME、または TIMESTAMP 型である必要があります。
YYYYWEEKは、定義されたサイクル内で週ごとに 1 つのテーブルシャードを作成します。テーブル作成前に、テーブルシャード総数をあらかじめ算出してください。PolarDB-X 1.0 インスタンスのバージョンは、5.1.28-1320920 以降である必要があります。
YYYYWEEK を使用したテーブルの作成
ステップ 1:必要なテーブルシャード数の算出
まずサイクル長を決定し、以下の計算を行います。
テーブルシャード総数 = 年間の ISO 週数 × サイクル長(年単位)。1 年間の ISO 週数は最大 53 週であるため、2 年間のサイクルでは 53 × 2 = 106 のテーブルシャードが必要です。
データベースシャードあたりのテーブルシャード数 = テーブルシャード総数 ÷ データベースシャード数(小数点以下を切り上げ)。可能な限り、この値をデータベースシャード数の整数倍になるよう調整することを推奨します。
例: データベースシャード数が 8、サイクル長が 2 年間の場合:
テーブルシャード総数:53 × 2 = 106
データベースシャードあたりのテーブルシャード数:106 ÷ 8 = 13.25 → 切り上げて 14
ステップ 2:テーブルの作成
Data Definition Language(DDL)文を用い、dbpartition by YYYYWEEK および tbpartition by YYYYWEEK を指定します。tbpartitions には、ステップ 1 で算出した値を設定します。
以下の例では、データベースシャード数が 8、各データベースシャードあたりのテーブルシャード数が 14 であり、2 年間のサイクルをカバーするテーブルを作成しています。
create table test_yyyyweek_tb (
id int,
name varchar(30) DEFAULT NULL,
create_time datetime DEFAULT NULL,
primary key(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
dbpartition by YYYYWEEK(create_time)
tbpartition by YYYYWEEK(create_time) tbpartitions 14;