web-dev-qa-db-ja.com

MySQL ENUMタイプと結合テーブル

私の要件

テーブルはstatus列を維持する必要があります。

この列は、5つの状態のいずれかを表します。


初期設計

私はそれを整数列にして、数値を使用して状態を表すことができると考えました。

  • 0 =開始
  • 1 =実行中
  • 2 =クラッシュした
  • 3 =一時停止
  • 4 =停止

アプリで整数から文字列の説明へのマッピングを維持したくないので、それらを(FKリレーションに依存して)別の状態説明テーブルに配置する予定です。

その後、MySQLが私の要件に完全に一致するENUMタイプを持っていることを発見しました。 MySQLへの直接の依存関係以外に、ENUMタイプを使用することの落とし穴はありますか?

56
ashitaka
  • ENUMの値のセットを変更するには、ALTER TABLEが必要です。これにより、テーブルの再構築が発生する可能性があります-非常に負荷の高い操作です(ENUM定義の最後に新しい値を1つ追加するだけでは、テーブルの再構築は行われません。ただし、1つ削除するか、順序を変更すると、テーブルが再構築されます)。一方、ルックアップテーブルの値のセットの変更は、INSERTまたはDELETEと同じくらい簡単です。

  • 廃止された属性や、ユーザーインターフェイスのドロップダウンリストに追加できる属性など、他の属性をENUMの値に関連付ける方法はありません。ただし、ルックアップテーブルには、そのような属性の追加の列を含めることができます。

  • ENUMをクエリして個別の値のリストを取得することは非常に難しく、基本的にはINFORMATION_SCHEMAからデータ型定義をクエリし、返されたBLOBからリストを解析する必要があります。テーブルからSELECT DISTINCT statusを試すこともできますが、これは現在使用中のステータス値のみを取得するため、ENUMのすべての値とは限りません。ただし、ルックアップテーブルに値を保持すると、クエリ、並べ替えなどが簡単になります。

ご存知のように、私はENUMの大ファンではありません。 :-)

列を固定値のセットと単に比較するCHECK制約にも同じことが当てはまります。 MySQLはとにかくCHECK制約をサポートしていません。

更新:MySQL 8.0.16に CHECK制約 が実装されました。

95
Bill Karwin

これが enumの速度比較 に関する記事です。多分それはいくつかのヒントを与えます。私見それは、99%の確率で将来変更されない文字列の固定リスト( "はい/いいえ"、 "子供/大人")での使用に限定されるべきです。

11
Riho

Mysqlの列挙型は、すでに説明されている理由により悪いです。
私は次の事実を追加できます:Enumはサーバー側でのいかなる種類の検証も保証しません。 enum定義に存在しない値を持つ行を挿入すると、enumフィールド宣言のNULL機能に応じて、DBにNiceまたはNULL値が取得されます。

Tinyintsについての私のポイント:
-列挙型は65535個の値に制限されています
-256を超える値が必要ない場合、tinyintは各行に必要なスペースが少なくなり、その動作ははるかに「予測可能」になります。

7
MatthieuP

DBに大量のデータがある場合(より多くのデータよりもRAM)であり、ENUM値が変更されない場合、結合ではなくENUMを使用します。もっと早く。
考えてみてください。結合の場合、外部キーのインデックスと、他のテーブルの主キーのインデックスが必要です。リホが言ったように、ベンチマークを見てください。

3
karl