skillup

技術ブログ

Database

論理設計のアンチパターン その2

投稿日:

今回は論理設計のアンチパターンの続きです。

今までに比べると何も意図がないというものではなく、パフォーマンスを考えて設計されているようなものが多いです。

ただし、中には絶対に許されないタイプのものもあるため、注意が必要なようです。

テーブル分割

水平分割

年度 会社コード 売上
2001 c001 2,000
2001 c002 3,000

これは例えば上記のようなテーブルがあったとして、パフォーマンス向上を目的として、レコード数を絞りたいがために年度ごとにテーブルを分割してしまうようなケースです。

意図はありますが、現実として下記のような欠点があります。

分割する意味的な理由がない

テーブルを分割する場合、正規化すべき理由がなければ基本的にテーブルを分割すべきではありません。

拡張性に乏しい

このテーブルの場合、前年度のデータを総なめで検索することがないという前提が常に成り立っています。そしてその前提が常になりたつかどうかは保証できませんし、カラムを追加する場合、複数のテーブルへの追加する必要がでてきます。

他の代替手段がある

こうした水平分割に代わる代替手段としてパーティションという機能があります。

パーティション機能を用いることで、テーブルを分割することなく、特定のキーを軸として物理的に書く領域を分離することが可能になり、SQLがアクセスするレコード数を1/nに減らすことができます。

インデックスとパーティションのどちらを使うかで迷うことがあるようですが、パーティションは一般的にはカーディナリティが小さく、値の変更があまり起きない列をキーにするときに利用します。

典型的な例としては「年」や「都道府県」などカーディナリティが十~数十のものが対象になります。

垂直分割

これは水平分割よりもさらによくありそう。

会社コード 社員ID 名前 年齢 部署コード
c001 s001 山田 23 m001
c001 s002 鈴木 33 m002
c002 k001 渡辺 44 p002

こういったテーブルを 会社コード、社員ID、名前、年齢のテーブルと 会社コード、社員ID、名前、部署コードのテーブル分けることを垂直分割といいます。

これも正規化といった点から分割すべきでないテーブルですね。なんとなく意味的に分けておきたいからといった理由でたまに見かけることがあります。

しかし、これらも下記のような代替手段があることからそれらを使うべきです。

集約

列の絞り込み

本来のテーブルから特定の参照したい列だけを絞ったテーブルを新しいテーブルを作成し、定期的に同期するようにします。このようにして作られるテーブルのことをデータマート、あるいは単にマートと呼びます。

サマリーテーブル

サマリーテーブルも集約の一手段です。列の絞り込みと違い、集計関数を使い、レコードを集約した状態で保持することです。例えば社員の平均年齢を見るときに会社コードごとの平均年齢を作成したテーブルをあらかじめ作っておくなどがこのようなテーブルになります。

ともにもしテーブルを分割したい場合には上記のような技術を使うことが望ましいです。ただし、ともに同期しておかないと整合性がとれなくなることやこれらを作ることでストレージの容量を消費することにもつながります。これらがデメリットです。

不適切なキー

キーに関してはなるべく固定長文字列を使うべき、というのが本来のあり方のようです。

というのもキーはその性質上不変であることが望ましいため、長さが変わる可能性があるものはふさわしくないということですね。

また全く同じ文字列でも固定長文字列と可変長文字列では違った値として判定されます。私が今までやってきた現場ではそこまでの意識がなかったのか。ほぼ可変長文字列でしたね・・・・

ダブルマスタ

これは全く同じ性質のテーブルが2つ(あるいはそれ以上)作られてしまうことです。

0からシステムを構築した場合このようなことはめったに起きないのですが、もともと別のシステムで利用されていたマスタ同士が、システム統廃合によって同じドメインに存在する、となったときにこのようなことが起こってしまうようです。この場合、やはりデータをしっかり精査して、1つのテーブルに収めるのが正しい手法です。

-Database
-

執筆者:


comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

関連記事

no image

cake sql系+リレーション+ヘルパー

先月末に引き続いてcakeネタをもりっといきます。 といっても自分用の小ネタリンク集です。 Contents1 sql系の小ネタ1.1 findとread1.2 find(‘count&# …

no image

sourceコマンドに関して(Linuxサーバー&MySQL)

Linux上ではコマンドをテキストファイルに記述して、

と入力すると命令を実行してくれます。 シェルスクリプトよりもお手軽に実行できる …

no image

MySQL小ネタ テーブル単位のリストア・SQLの小ネタ(バックスラッシュの検索)

MySQLのちょい小ネタ。 Contents1 テーブル単位でバックアップ&リストア2 バックスラッシュの入ったSQLについて テーブル単位でバックアップ&リストア 1 通常のdump(データベース単 …

no image

データベース設計のアンチパターン リトライ+バッチ分割+バッチの再利用不可

Contents1 リトライ1.1 デメリット1.2 対策2 バッチ分割2.1 デメリット2.2 対策3 バッチ再利用不可3.1 デメリット3.2 対策 リトライ ※OLTP=オンライントランザクショ …

no image

SQL サブクエリ

前回の問題をサブクエリを使って解きます。前年度の売上を出すのが一番難しいので、それを出す方法です。MySQLだとそもそも分析関数が存在しないので・・ [crayon-5f72a3bf2b6537005 …