MySQL列挙型のテスト例

MySQL列挙型のテスト例

プロジェクトを開発しているとき、支払い済み、支払済み、クローズ済み、返金済みなどの注文ステータスなどのステータス フィールドに遭遇することがよくあります。以前のプロジェクトでは、これらのステータスは数値としてデータベースに保存され、次に定数を使用して PHP コードでマッピング テーブルが維持されていました。次に例を示します。

定数STATUS_PENDING = 0;
定数STATUS_PAID = 1;
定数STATUS_CLOSED = 2;
定数STATUS_REFUNDED = 3;

しかし、実際に使用してみると、それほど使いやすいものではないことがわかりました。さまざまな理由(バグの追跡、一時的な統計ニーズなど)により、MySQL サーバーにログインして、いくつかの SQL クエリを手動で実行する必要があることがよくあります。多くのテーブルにはステータス フィールドがあるため、SQL を記述するときに、PHP コード内のマッピング関係を参照する必要があります。注意しないと、異なるテーブルのステータス番号を混同し、大きな問題が発生する可能性があります。

そこで、新しいプロジェクトでさまざまな状態を保存するために、MySQL の enum 型を使用することにしました。使用中に、Laravel 移行ファイルで enum 型を使用してテーブルに変更を加えると (enum 型以外のフィールドを変更した場合でも)、エラーが報告されることがわかりました。

[Doctrine\DBAL\DBALException]
不明なデータベース タイプ列挙が要求されました。Doctrine\DBAL\Platforms\MySQL57Platform ではサポートされていない可能性があります。

検索した結果、doctrine は MySQL enum をサポートしていないことがわかりました。記事には enum の 3 つの欠点が挙げられています。

新しい列挙値を追加する場合は、テーブル全体を再構築する必要があり、データ量が多い場合は数時間かかることがあります。

列挙値のソート規則は、リテラル値のサイズではなく、テーブル構造の作成時に指定された順序に基づきます。

列挙値の検証に MySQL に依存する必要はありません。デフォルト設定では、無効な値を挿入すると、最終的には null 値になります。

新規プロジェクトの実際の状況から判断すると、ステータスフィールドをソートする必要はほとんどありません。 必要になったとしても、テーブル構造を設計するときに順序を設定できるため、デメリット 2 は無視できます。 デメリット 3 は、コード標準、挿入前/更新前検証などを通じて回避できます。 デメリット 1 については、テストを行う必要があります。

テスト準備

まずテーブルを作成します。

テーブル `enum_tests` を作成します (
 `id` int(10) 符号なし NOT NULL AUTO_INCREMENT,
 `status` enum('pending','success','closed') COLLATE utf8mb4_unicode_ci NOT NULL,
 主キー (`id`)
) エンジン=InnoDB デフォルト文字セット=utf8mb4 照合=utf8mb4_unicode_ci;

次に 100 万個のデータを挿入します。

カウント = 1000000;
1000 バイト
$データ = [];
foreach (['保留中', '成功', '終了'] を $status として) {
  $data[$status] = [];
  ($i = 0; $i < $bulk; $i++) の場合 {
    $data[$status][] = ['status' => $status];
  }
}

($i = 0; $i < $count; $i += $bulk) の場合 {
  $status = array_random(['保留中', '成功', '終了']);
  EnumTest::insert($data[$status]);
}

テストプロセス

テスト1#

列挙値リストの最後に払い戻しの値を追加します。

ALTER TABLE `enum_tests` CHANGE `status` `status` ENUM('pending','success','closed','refunded') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL;

出力:

クエリは正常、影響を受けた行は 0 行 (0.04 秒)
レコード: 0 重複: 0 警告: 0

結論: 最後に列挙値を追加してもコストはほとんどかかりません。

テスト2:#

追加した値を削除して払い戻し

ALTER TABLE `enum_tests` CHANGE `status` `status` ENUM('pending','success','closed') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL;

出力:

クエリは正常、1000000 行が影響を受けました (5.93 秒)
レコード: 1000000 重複: 0 警告: 0

結論: 未使用の列挙値を削除するには、依然としてテーブル全体のスキャンが必要であり、コストはかかりますが、許容範囲内です。

テスト3:#

値のリストの最後ではなく真ん中に払い戻しを挿入します

ALTER TABLE `enum_tests` CHANGE `status` `status` ENUM('pending','success','refunded', 'closed') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL;

出力:

クエリは正常、1000000 行が影響を受けました (6.00 秒)
レコード: 1000000 重複: 0 警告: 0

結論: 元の列挙値リストの途中に新しい値を追加するには、テーブル全体のスキャンと更新が必要になり、コストがかかります。

テスト4:#

値のリストの途中にある値を削除する

ALTER TABLE `enum_tests` CHANGE `status` `status` ENUM('pending','success','closed') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL;

出力:

クエリは正常、1000000 行が影響を受けました (4.23 秒)
レコード: 1000000 重複: 0 警告: 0

結論: テーブル全体をスキャンする必要があり、コストが非常にかかります。

テスト5:#

ステータスフィールドにインデックスを追加し、上記のテストを実行します。

ALTER TABLE `enum_tests` ADD INDEX(`status`);

テスト 2 ~ 4 の消費時間は実際には増加していることがわかりました。これは、インデックスを同時に更新する必要があることが原因であると考えられます。

結論

新しいプロジェクトでは、新しい列挙値のみが登場します。将来的に一部の状態が放棄されたとしても、列挙値リストを調整する必要はありません。そのため、プロジェクト内の状態を格納するためのデータ型として列挙型を導入することにしました。

<<:  Vueは適切なスライドアウトレイヤーアニメーションを実装します

>>:  Linux でファイルの種類を理解して識別する方法

推薦する

IDEA が Docker を統合してリモート展開を実現するための詳細な手順

1. Dockerサーバーへのリモートアクセスを有効にするdocker が配置されているリモート サ...

MySQLインデックスが使用されない状況のまとめ

MySQL のインデックスの種類一般的に、次の 4 つのカテゴリに分類できます。通常のインデックス:...

Linux7で仮想ホストを実装する3つの方法

1. 同じIPアドレス、異なるポート番号仮想ホスト 1: ホスト IP アドレスは 172.16.3...

入力ボックスのコンテンツプロンプトと非表示機能を実装する JavaScript

入力ボックスが小さい場合、内容を入力した後に、入力内容が拡大されたプロンプト ボックスを表示したいこ...

ウェブ音楽プレーヤーを実現する js

この記事では、参考までに簡単なHTMLと音楽プレーヤーの制作コードを紹介します。具体的な内容は以下の...

Bootstrap 3.0 の特殊効果の学習ノート(表示と非表示、フローティングの除去、閉じるボタンなど)

この記事の主な内容は次のとおりです。 1. 閉じるボタン2.キャレット3. フローティングを素早く設...

Windows 7 の mysql6.x で中国語の文字化けが発生する問題に対する完璧な解決策

1. コマンドラインでMySQLサービスを停止します: net stop mysql stop my...

docker ログが取得できない問題の解決方法

毎日サービスをチェックしているときに、portainer からコンテナ ログを確認しようとしたところ...

行の高さと垂直方向の配置に関する包括的な理解

前の単語line-height、font-size、vertical-align は、インライン要素...

MySQLサービスが起動しても接続されない問題の解決策

mysql サービスは開始されていますが、接続できません。この問題を解決するにはどうすればよいでしょ...

CentOS 7 に MySQL 8 をインストールするための詳細なチュートリアル

準備するこの記事の環境情報: ソフトウェアバージョンセントOSセントOS7.4マイグレーション8.0...

MySql ビュー トリガー ストアド プロシージャの詳細な説明

ビュー:一時テーブルを繰り返し使用する場合、将来の使用を容易にするために別名を付けることができます。...

Linux でコマンドまたはプロセスの実行時間を調べる方法

Unix ライクなシステムでは、コマンドまたはプロセスの実行がいつ開始されたか、またプロセスがどのく...

MIME エンコーディングの概要 (オンライン情報と実際の経験から統合)

1. MIME: 多目的インターネットメール拡張インペリアル カレッジ オブ コンピュータ オンラ...