LoginSignup
1
1

More than 3 years have passed since last update.

SQLアンチパターン メタデータトリブル

Last updated at Posted at 2020-08-27

メタデータトリブル

どんなに優れたデータベースでもデータが増えることでパフォーマンスは低下していく。
インデックスを使用することで状況は改善するが、それでもデータの増加によってパフォーマンスが低下していく。

メタデータトリブルとはデータ増加につれてパフォーマンスが低下することに対応するための構造を指す。
具体的には以下のようなパターンが当てはまる。

  • 行数の多いテーブルを複数のテーブルに分割する
  • 列を複数列に分割する

表で表すと以下の通り。

book

book_id release_date title
1 2019-06-01 エンジニアになろう1巻
2 2020-01-03 エンジニアになろう2巻
3 2020-04-03 エンジニアになろう3巻
4 2020-12-31 エンジニアになろう4巻
5 2021-03-02 エンジニアになろう5巻
6 2021-06-02 エンジニアになろう6巻
7 2021-09-02 エンジニアになろう7巻
8 2021-12-02 エンジニアになろう8巻

上記の表は、本のタイトルと発売日を格納したシンプルなテーブル。
現在は「エンジニアになろう」シリーズの書籍が格納されている。
1タイトルのみ格納されていて巻数もまだ8巻しかない。

しかし今後このサービスで数万タイトル扱うこととなりテーブルを年ごとに分割し格納する構造に変更した。
以下の構成が今回のメタデータトリブルパターンに該当する

2019_release

book_id release_date title
1 2019-06-01 エンジニアになろう1巻

2020_release

book_id release_date title
1 2020-01-03 エンジニアになろう2巻
2 2020-04-03 エンジニアになろう3巻
3 2020-12-31 エンジニアになろう4巻

2021_release

book_id release_date title
1 2021-03-02 エンジニアになろう5巻
2 2021-06-02 エンジニアになろう6巻
3 2021-09-02 エンジニアになろう7巻
8 2021-12-02 エンジニアになろう8巻

上記のパターンは発売した年でテーブルを分割し1テーブルでデータを持つよりレコード数が減りパフォーマンスの低下を軽減ですることを目的とした構成である。

デメリット

  • テーブルの増殖
  • データの整合性管理
  • データの同期
  • 一意性の保証
  • テーブルをまたいだクエリ実行
  • メタデータの同期
  • 参照整合性の管理

テーブルの増殖

データを複数のテーブルに分割する際、どのレコードがどのテーブルに属しているか定義するポリシーが必要となる。

2019_release

book_id release_date title
1 2019-06-01 エンジニアになろう1巻

2020_release

book_id release_date title
1 2020-01-03 エンジニアになろう2巻
2 2020-04-03 エンジニアになろう3巻
3 2020-12-31 エンジニアになろう4巻

2021_release

book_id release_date title
1 2021-03-02 エンジニアになろう5巻
2 2021-06-02 エンジニアになろう6巻
3 2021-09-02 エンジニアになろう7巻
8 2021-12-02 エンジニアになろう8巻

上記の例ではテーブルを年ごとに分かれている。
データを挿入する際は年によって挿入するテーブルを選択する必要がある。

また、今回の例のように年ごとにテーブルを分割していた場合、2021年が終了して2022年になっていた際に「2022_release」の作成を忘れて「2022_release」にデータを挿入しようとした際アプリけーーションからエラーが発生するようになる。

データの整合性管理

2019_release

book_id release_date title
1 2019-06-01 エンジニアになろう1巻

2020_release

book_id release_date title
1 2020-01-03 エンジニアになろう2巻
2 2020-04-03 エンジニアになろう3巻
3 2020-12-31 エンジニアになろう4巻

2021_release

book_id release_date title
1 2021-03-02 エンジニアになろう5巻
2 2021-06-02 エンジニアになろう6巻
3 2021-09-02 エンジニアになろう7巻
8 2021-12-02 エンジニアになろう8巻

上記のテーブル構成で、新たに以下のデータを挿入したい。

release_date title
2021-12-30 エンジニアになろう番外編

挿入したいテーブルは「2021_release」ですが、日時を見て自動的に挿入テーブルを選択する方法がないためcheck制約を設ける必要があります。

データの同期

2019_release

book_id release_date title
1 2019-06-01 エンジニアになろう1巻

2020_release

book_id release_date title
1 2020-01-03 エンジニアになろう2巻
2 2020-04-03 エンジニアになろう3巻
3 2020-12-31 エンジニアになろう4巻

2021_release

book_id release_date title
1 2021-03-02 エンジニアになろう5巻
2 2021-06-02 エンジニアになろう6巻
3 2021-09-02 エンジニアになろう7巻
8 2021-12-02 エンジニアになろう8巻

上記のデータにて、「2020_release」に挿入されている「エンジニアになろう2巻」が「2020-01-03」発売ではなく「2019-12-31」だった場合、該当データをUPDATEするだけでは別の年数のテーブルに格納されてしまうことになる。

2020_release

book_id release_date title
1 2019-12-31 エンジニアになろう2巻
2 2020-04-03 エンジニアになろう3巻
3 2020-12-31 エンジニアになろう4巻

修正するためには対象テーブルからデータを削除して別のテーブルにインサートする必要がある。

一意性の保証

テーブルを分割した場合、主キーの値が一意であることを保証する必要がある。
以下の場合によって対応が異なる。

  • シーケンスオブジェクトをサポートするデータベースを使用している場合、同一のシーケンスオブジェクトを使用して、分割されたテーブルに対して主キーの値を生成できる。

  • シーケンスオブジェクトがなく、テーブルごとにID生成のみをサポートするデータベースを使用している場合主キーを作成するためにテーブルを定義する必要がある。

テーブルをまたいだクエリ実行

複数テーブルをまたいでテーブルを参照する必要が出てきた。
その際はUNIONを使用して該当を参照する必要がある。

テーブルが追加された場合はその都度参照テーブルを追加する必要がある。

メタデータの同期

◯◯◯◯_release

book_id release_date title price

上記のテーブル構成に販売価格を管理する列を追加することとなった。
新しい列はALTER文を用いて追加できるが、年ごとにテーブルが分割されているため対象テーブル全てに対して共通する列を追加する必要がある。

参照整合性の管理

2019_release

book_id release_date title
1 2019-06-01 エンジニアになろう1巻

上記のテーブルに各書籍に紐づいたコメントを管理するテーブルを作成したい。

しかし、ポリモーフィック関連の記事で詳細に記載したが、親テーブルが複数になるため外部キーを設定することができない。

解決策

パーティショニングの使用

パーティショニングを使用することでテーブル分割の欠点を解消しつつ巨大なテーブルを分割するメリットを得られる。
テーブルは物理的に分割されているが1つのテーブルを扱うようにSQLステートメントを実行できる。

詳しくはわかりやすい記事があったため詳細はこちらを参照してください。

【MySQL】データベースのパーティショニングとはなんぞやという話

まとめ

データにメタデータを増殖させない

次回

ラウンディングエラー

参考文献

SQLアンチパターン

参考文献.jpg

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1