fbpx

メニュー

wpdb道場 (3) 〜データベースを設計する前に〜

高橋文樹 高橋文樹

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

昨晩更新するはずが、テレビを見ながらウイスキーをかっくらっていたら撃沈してしまいました。できれば今日中にブログを2本あげたいところです。

さて、前回まででMySQLのCRUDを一通り試してみましたが、ここで残念なお知らせです。前回は$wpdb->updateで投稿を更新したりしましたが、実のところ、ごく限られた状況でしか投稿テーブルをいじることはありません。

それはなぜかというと、WordPressにはそうしたデータベースを操作するための関数がすでに用意されているからですね。しかも、それを使った方がおそらくあなたの作る関数よりも高品質です。オープンソースで何年も使われているわけですからね。

ためしに、前回行った「wp_postmetaにデータを追加する」という機能を持った関数群を列挙してみます。

  • get_post_meta
  • add_post_meta
  • update_post_meta
  • delete_post_meta

どうでしょう、CRUDが全部揃っていますね。他にもいろいろあって、配列で取得したりとか、投稿IDを渡さなくても現在のループの投稿IDを自動的に取得するものとか、いろいろあります。

get_post_meta一つをとっても、データベースから値を取ってくるだけでなく、その値をオブジェクトキャッシュに保存したり、フィルターフックをかけたり、いろいろやってくれているんですね。

WordPress全般に言えることですが、こうした関数は「テンプレートタグ」という名前でうまい具合に隠蔽されています。

「では私がいままでやってきたことはなんだったのか?」と怒らないでくださいよ。これから「なにをしないでいいか」を知ればいいんです。ほら、ツアー旅行でいけないような場所に行きたかったら、まずは地図の読み方から始めないといけないでしょう。それと同じです。

データベース構造を知る

WordPressのデータベース構造はCodexに書いてあります。ちょっと図を拝借。

WordPress 3.8のER図。Codexより。
WordPress 3.8のER図。Codexより。

11個のテーブルがあり、それぞれの役割はこんな感じです。Codexにも書いてあるんですけどね。

 

wp_options
サイトの設定を保存するところ。サイト名、どのテーマやプラグインを使うかなどなど。プラグインの設定情報もここに保存されることが多いです。また、これはイケてない仕組みなのですが、Transientなどの一時キャッシュもこちらに保存されます。
wp_posts
投稿データ。タイトル、本文、日時、投稿者IDなどなど。
wp_postmeta
カスタムフィールド。post_idはwp_postsのIDですね。
wp_comments
コメントが保存されています。
wp_commentmeta
コメントのメタ情報。普通に使っている限りはほとんど使われません。プラグインなどでコメントの評価(星の数)を保存するようなやつはこれを使っているでしょう。
wp_links
リンクを保存するテーブル。はっきりいって、もういらないと思います。
wp_users
ユーザー情報のうち主要なものが保存されています。
wp_usermeta
ユーザー情報のうち、「その他」にあたるものが保存されています。プロフィールとか、そういうのですね。権限(Capability)もこちらに保存。
wp_terms
カテゴリーやタグなどの「用語」情報。ただし、カテゴリーとイコールではないことに注意してください。保存されているのはID、名前、スラッグ、グループだけです。この用語がカテゴリーであるのかタグであるのかは保存されていません。
wp_term_taxonomy
タクソノミー情報が保存されています。上述したwp_termsと組み合わせることとカテゴリーやタグを表現します。
wp_term_relationships
タクソノミーと投稿のひも付きが保存されています。object_idに投稿IDが、term_taxonomy_idにタクソノミーIDが保存されます。

 

WordPressのデフォルトテーブル構造はこんな感じですね。WordPressにテーブルを追加してなにかする場合、「ほんとうにこのテーブルで表現できないのか?」を考える必要があります。

たとえば、テキストコンテンツでタイトルがないようなものを「つぶやき」として保存したいなと考えたとしましょう。でも、それってカスタム投稿タイプで済んじゃいますよね。もし「つぶやきテーブル」が必要になるとしたら、どんな場合でしょうか。この答えは次回以降。

MySQLの重要な概念を3つ学ぶ

さて、デフォルトのテーブル構造がこんな感じというのを見た後で、重要な3つの概念を知っておきましょう。

  1. 正規化
  2. データ型
  3. ストレージエンジン

1. 正規化とは?

一つ「正規化」という概念を学びたいと思います。正規化とは、IDのような演算対象として望ましい数値などを正規系とし、商品名や記事タイトルといったデータが重複をしないようにテーブルを分離していくことを意味します。

Excelでなんらかのデータを管理していて、商品情報などが修正されたときにいちいち全部のセルを書き換えるのは大変ですよね。それを別テーブルで管理しておけば、一箇所変えるだけですみます。正規化をきちんと行うことは、データの整合性を保つことに役立ちます。

たとえば、購入情報のレコードをExcelのような伝票形式からMySQLのテーブルに解釈すると……

テーブルの正規化とは、こういう作業のことです。
テーブルの正規化とは、こういう作業のことです。

こんな風になりますね。すっきり。

なお、「小計は単価 x 個数で出せるのでは?」と思うかもしれませんが、商品金額は変わることが考えられるので、この場合は残しておきます。

もしWordPressの投稿とタグの紐付けが正規化されていなかったら、ものすごく横に長いExcelみたいなのになってしまいます。それをwp_posts, wp_terms, wp_term_taxonomy, wp_term_relationshipsという4つのテーブルにわけて表現しているわけですね。

もちろん、正規化によるデメリットもあり、それは主にパフォーマンスに関するものです。ただ、MySQLを作っている人がちゃんと正規化しろと言っていますし(参考:データベースアプリケーション開発を炎上させる負のスパイラル)、パフォーマンスの問題は時間とともに解決することがある(ex. SSDのサーバが安くなった、MySQLの新バージョンが出た、ect.)ので、積極的に正規化することをお勧めします。

ソシャゲなんかで異常にアクセスの多い値(たとえば、キャラクターのヒットポイントとか)は正規化しなかったりするらしいですが、知識が足りずに正規化ができないのと、いろいろ知った上であえて正規化しないのでは雲泥の差があります。

ともあれ、MySQLのテーブル構造設計においては、必要とされる情報をきちんと正規化しておく必要があるということです。リレーショナルデータベースの正規化というエントリーが参考になるので、読んでみてください。

2. データ型

MySQLデータベースはテーブルというExcelシートみたいなものを複数組み合わせたものなのですが、それぞれの列(カラム)にはデータ型というものがあります。保存すべきデータがいったいなんなのか、という形式を定義したものですね。

たとえば、保存するデータが文字列だったとしましょう。ところがどっこい、文字列でもこんだけいろんなタイプがあるんですね。

  • CHAR
  • VARCHAR
  • TEXT
  • BINARY
  • VARBINARY
  • ENUM
  • SET

DATETIME型とかももしかしたら文字列型に分類されるのかもしれません。あと、数値型というのもあります。

  • INT
  • FLOAT
  • DOUBLE
  • DECIMAL

これ以外に地理情報を格納できるGEOMERTY型などもあります。

で、こんなにある中どれを使えばいいの、となるのですが、それは目的にあった型を選べば良いのです。

IDだったらINT型、日付だったらDATETIME型、データの更新日を記録したかったらTIMESTAMP型。金額ならDECIMALにしておくと精度が高い(らしい)ですし、地理情報をGEOMETRYの一種であるPOINT型にしておけば、特定の範囲に含まれる地点をピックアップするクエリがサポートされます。

いずれにせよ、適した形のデータ型を選べばよく、全部覚えている必要はありません。

ちなみに、WordPressのpost_metaはなんでもかんでも入れられる代わりに、meta_valueのデータ型がTEXTとなっています。このため、数値順に並べ替えたり、検索したりすると遅いんですね。

3. ストレージエンジン

ストレージエンジンとは、テーブルの保存形式です。いくつか種類はあるのですが、通常使われるのはMyISAMもしくはInnoDBです。

WordPressはデフォルトだと全部MyISAMですが、これは後方互換性(というより、当初がそうだったからいまもそうなっているという惰性)のためであり、基本的にはInnoDBにしたほうがよいです。

MySQL5.6ぐらいから、MyISAMにしかない機能というのはほとんどなくなってしまった上に、InnoDBの方が熱心に機能改善されている印象です。

他にどんなストレージエンジンがあるのかというと、特殊な用途のものが多いので、あんまり知らなくてもいいかな、と。それよりはレプリケーションとか、MySQLクラスタとか、NoSQLの知識などの横に広がりを持った知識を身につけたほうがいいですね。

まとめ

  • WordPressのテーブルは11個あり、使えるものはそのまま使い、ないものを作る
  • MySQLの設計には正規化という作業が必要
  • MySQLのカラムにはデータ型があり、その都度で適切なものを選ぶべし
  • MySQLのテーブルにはストレージエンジンというものがあり、基本InnoDBでおk。

というわけで、データベース設計の前段階を終えます。次回、ユーザーをフォローするためのテーブル設計を行い、その次にプラグインを作り始めます。

[429] [429] Client error: `POST https://webservices.amazon.co.jp/paapi5/getitems` resulted in a `429 Too Many Requests` response: {"__type":"com.amazon.paapi5#TooManyRequestsException","Errors":[{"Code":"TooManyRequests","Message":"The request was de (truncated...)

すべての投稿を見る

高橋文樹ニュースレター

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