MySQLでテーブルを作る際に注意すべきこと

こんにちは。 エキサイト株式会社の三浦です。

アプリケーションを作る上で、データを格納するためにMySQLを立ててテーブルを作成する機会は多いと思います。 今回は、テーブルを作成する際に注意すべきことをいくつか書いていきます。

一意なデータにはユニーク制約をつける

当然といえば当然ですが、データ構造上一意になるデータにはユニーク制約をつけましょう。

「データを追加・更新するときに気をつけるから大丈夫」と思っていても、何かのタイミングでうっかり重複してしまう可能性は捨てきれません。 また、ユニーク制約がある事自体が仕様となり、後から使用する人に親切な作りにもなります。

参照順序を考える

MySQLでは、 utf8_general_ci のようなアルファベットの大文字・小文字を区別しない参照順序や、 utf8_bin のような大文字・小文字を区別する参照順序、絵文字を認識してくれる utfmb4 系の参照順序など、さまざまな種類の参照順序があります。

大文字・小文字の区別の例で考えると、多くの場合アプリケーションコードでは文字列を扱うときに大文字・小文字は自然と区別されて扱われるので、MySQLutf8_general_ci (大文字・小文字を区別しない参照順序)を使っており、かつそれを認識しないまま使用していると、思わぬところで不具合が生じる恐れがあります。

入れるデータにとってどの参照順序が適切かを考え、適切なものを選択しましょう。

日付を扱う際は timestamp ではなく datetime を使う

日時を扱う場合、 timestamp 型と datetime 型のどちらかを選択することができますが、 timestamp ではサポート範囲の関係で、2038年以降は日付が正しく表示されないという問題があります。

datetime 型を使うようにしましょう。

AutoIncrementを使用するカラムの型に適切なものを選ぶ

AutoIncrementを使用するカラムでは、数値を使い切らないよう適切な型を選ぶ必要があります。

多くの場合は int 型で良いかもしれませんが、頻繁にdelete/insertが走るようなテーブルであれば bigint 型の方が良いでしょう。

何をカラムとして持ち、何を別テーブルに持つか判断する

例えば記事データを持つテーブルを作る時、記事のタイトルや本文は記事テーブルのカラムとして持っておいても不思議ではありません。

一方で、記事のタグはどうでしょうか? 多くの場合、タグは1つの記事に複数持つものです。 その場合、 tag1 tag2 ... などのカラムを持つべきでしょうか?

こういったカラムについては、記事テーブルにカラムとして持つより、記事タグテーブルとして別テーブルに持ち、記事テーブルと連結して使うほうが良いでしょう。

このあたりをすべてそのまま記事テーブルにカラムとして作るようにすると、ほとんどNULLしか入っていないカラムができたり、使われているのかどうかわからないカラムが大量にできてしまったりします。

可能な限りデフォルトNotNullにする

NULLは、MySQLにとってもアプリケーションコードにとっても特別な値であり、取り扱いが難しいデータです。 MySQLの多くの型ではデフォルト値を入れることが可能なので、可能な限りカラムはNotNullとし、デフォルト値を入れるようにしましょう。

最後に

最近よくMySQLを触る機会があったので、気になったところを並べてみました。

データ構造は一回作って使われ始めると修正するのが非常に困難なものなので、最初に作るときにきちんと熟考するようにしましょう。