fbpx

メニュー

wpdb道場 (4) 〜データベースを設計しよう〜

高橋文樹 高橋文樹

この投稿は 9年半 前に公開されました。いまではもう無効になった内容を含んでいるかもしれないことをご了承ください。

前回まででMySQLの特徴となるものをぼんやりとつかみました。では、どのようなテーブル構造にしたらよいでしょうか。これについてちょっとばかり頭をひねってみましょう。

テーブルを設計しよう!

さて、今回目的とするプラグインは、第1回で宣言した通り、「ユーザー同士でフォローしたりフォローされたりすること」でした。では、このフォローされたりフォローしたりしているという状況はMySQLのデータベースで表現するとどうなるのでしょうか。

  • AさんはBさんをフォローしている
  • BさんはCさんをフォローしている
  • CさんはAさんをフォローしている
  • AさんはBさんにフォローされている
  • ……

こんな感じのデータをMySQLで表現するわけですね。

1 fact in 1 place

さて、データベース設計の原則に ”1 fact in 1 place” という言葉があります。直訳すると「1つの事実は1つの場所に」ですね。

上では「フォローされている」という「フォローしている」という動詞をわざわざ2つ書きましたが、これは同じ事実を2つの仕方で表しただけです。

「AさんがBさんをフォローしている」と「BさんはAさんにフォローされている」は、当人たちの捉え方はそれぞれでしょうが、はたから見ていると1つの客観的事実にすぎません。

したがって、くれぐれも2つのテーブルを作ろうと思わないでください。こんな感じのテーブルで十分でしょう。

フォローしている人 フォローされている人
Aさん Bさん
Bさん Aさん
Cさん Aさん

仮に、このテーブルをfollowersテーブルとしましょう。WordPressの場合は接頭辞が付くので、wp_followersとかになりますかね。

ユニークなのはどれ?

データベースのテーブルに保存されるデータは「ユニーク」である必要があります。「ユニーク」とは、気が利いていて面白い事がいえるとかそういうことではなく、「唯一の」という意味ですね。全員が面白いとか、そんなことあるわけないじゃないですか。

wp_postsを試しに見てみると、IDというカラムが存在します。

wp_postsのテーブル構造
wp_postsのテーブル構造

これはAuto Increment属性を持っており、データを追加するごとに1ずつ増えていきます。たとえ削除したとしても、テーブルは自分が発行したIDを覚えていて、次に追加した時はまた1ずつ増えていくのですね。これにより、投稿IDは絶対に重複することはありません。

では、wp_followersにもそういうIDが必要なのでしょうか? 今のところは、どうやら必要なさそうです。というのは、AさんがBさんをフォローしているという状況がダブることは現実的にありえないからです。

幸い、MySQLでは複数のカラムを組み合わせて「この組み合わせはユニークじゃなきゃダメ」と宣言することができます。この宣言をPRIMARYキーと言います。wp_postsを見てみると、IDにPRIMARYキーが付与されていますね。

IDにPRIMARYキーが付与されている
IDにPRIMARYキーが付与されている

ちなみに、PRIMARYキーが重複するような値を保存しようとすると、どうなるでしょう? なんと、エラーになって保存できないんですね。お利口です。

正規化してみる

上に書いたデータの例では、Aさん、Bさんなどと書いていましたが、正規化を行うと、ユーザーIDを使うことになります。

wp_usersテーブル
wp_usersテーブル

IDのような数字だと、検索しやすいですし、ユーザーが名前を変更したからといってfollowersテーブルのデータをすべて変更したくないですもんね。

カラム名などを特に決めていませんでいたが、フォローしている人(主語)のカラムをfollower_idに、フォローされている人(目的語)のカラムをuser_idにしましょう。wp_posts.IDとwp_users.IDは両方ともINT型つまり、整数なので、これらのカラムも整数にします。

あと、データが作成された日時も取っておきたいので、このカラム名をcreatedにしましょう。このカラムはDATETIME型ですね。(なぜタイムスタンプにしないのかは後述)そうすると、先ほどのテーブルはこんな感じになります。

wp_followers
follower_id user_id created
1 2 2014-12-10 21:00:00
2 1 2014-12-11 09:00:00
3 1 2014-12-13 12:30:00

さて、これでテーブルの設計は十分でしょうか? たぶん、不十分です。はっきりいって、僕もよくわかりません。まだ作ってもいないものの完成形がわかるわけないじゃないですか。

そうですね、たとえば、twitterでよく使われる機能に「ブロック」というものがあります。このテーブル構造では「ブロック」を表現できないですね。

しかし、もうそろそろプラグインを作り始めるべきです。我々は準備に時間をかけすぎました。なぜか? それは、人生の時間が有限であり、人は永遠に設計し続けることはできないからですよ。

データベース設計はいつでも見直せるべき

データベース設計というのは、慎重で、家の建築計画のように取り返しのつかないことだということがよく言われます。

しかし、僕個人の意見では「いつでもテーブル設計を変更できるようにすべき」です。もちろん、クリティカルなデータというのは存在します。たとえば、お客さんから商品の注文を保存していたテーブルがあったとしましょう。それをぶっ飛ばしたらヤバいですよね。

そうするとどういうことになるかというと、なんかよくわかんないけどたくさんデータを保存できるようにしようと思って、option1, option2, option3…… という具合に、やたら横に長い受注テーブルが出来上がるんですよ。

その状態で運用を続けていると、それなりにoption1などの役割がはっきりしてきて、「どうやらoption1には商品を発送したときの問い合わせ番号を保存するっぽい」となったりします。

本来であれば、そこで正規化をし、受注メタ情報みたいなテーブルを作って、受注テーブルのカラムをドロップ(削除)すべきなのですが、「間違えて消したらどうする」「その間商用環境は止まるのか?」「触らぬDBに祟りなし」みたいな内外のプレッシャーで結局そのまま使い続け、なんかカラムが足りなくなって、わけのわからないシリアライズされた配列やJSONデータを1つのカラムに保存するような羽目になるわけです。

その結果、検索性も低くなり、だんだん醜悪なコードが増えてきて、最終的にはおいそれと触れなくなってしまいます。そのまま3年ぐらいたって、人が入れ替わり、新しく入ってきた人が「臭う! このコードは臭うぞ!」と叫んでコードスメル案件の出来上がりです。

もちろん、商用環境でバリバリ動いているデータベースをいじるのは大変プレッシャーがかかることですが、だからこそ、いつでもその構造を見直せるだけの知識を身につけておきたいですね。こまめに見直せば、そんなにひどいことにはならないですよ。

そのための知識は今後、少しずつ小出しにしていきます(=このブログをフォローすべき)

まとめ

というわけで、今回のまとめは以下のとおり。

  1. 1 fact in 1 place.
  2. テーブルに保存するデータはユニークじゃなきゃダメ!
  3. テーブルの設計はいつでも見直せるようにしよう

次回からはいよいよWordPressのプラグインを作り始めます。いやー、1日2回もブログ更新したので俺ベントカレンダーの借金が1減りました。よかったよかった。

すべての投稿を見る

高橋文樹ニュースレター

高橋文樹が最近の活動報告、サイトでパブリックにできない情報などをお伝えするメーリングリストです。 滅多に送りませんので、ぜひご登録お願いいたします。 お得なダウンロードコンテンツなども計画中です。