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 でファイルの種類を理解して識別する方法

推薦する

nginx でのリクエストのカウント追跡の簡単な分析

まずは適用方法を説明します。nginxモジュールにはjtxyとjtcmdの2つがあります。 http...

クールな充電アニメーションを実現する純粋なCSS

CSS のみを使用してどのような充電アニメーション効果を作成できるかを見てみましょう。バッテリーを...

nginx プロキシ サーバーで双方向証明書検証を構成する方法

証明書チェーンを生成するスクリプトを使用して、ルート証明書、中間証明書、および 3 つのクライアント...

docker を使用して kafka プロジェクトをデプロイする Centos6 方法の分析

この記事では、Docker を使用して Centos6 に Kafka プロジェクトをデプロイする方...

Windows 環境に mysql-8.0.11-winx64 をインストールする際に発生する問題を解決する

MySQL インストール パッケージをダウンロードします。mysql-8.0.11-winx64 を...

美容・スタイリングウェブサイト向けのカラーマッチングテクニックと効果表示

色はあらゆるウェブサイトにとって最も重要な要素の 1 つであり、閲覧者に大きな影響を与えるため、色の...

実践で遭遇するフロントエンドの基本(HTML、CSS)

1. div css マウスの手の形は cursor:pointer; です。 2. HTML の相...

jsは画像切り取り機能を実現する

この記事の例では、画像の切り取りを実現するためのjsの具体的なコードを参考までに共有しています。具体...

Vue でのキープアライブコンポーネントの使用例

問題の説明(キープアライブとは何か)キープアライブ 名前の通り、アクティブな状態を維持します。誰が活...

Windows 10 に Apache 2.4.41 をインストールするチュートリアル

1. Apache 2.4.41 のインストールと設定最初のステップは、以下に示すように、https...

ウェブページ作成に役立つコード

<br />ホームページの右側にあるスクロールバーを削除するにはどうすればよいですか? ...

MySQLクエリが遅い理由

目次1. 遅いところはどこですか? 2. 不要なデータをクエリしましたか? 1. 不要なレコードをク...

JavaScript 上級プログラミング: 変数とスコープ

目次1. 元の値と参照値2. インスタンス3. 範囲1. 元の値と参照値6 つの単純なデータ型の値は...

MySQL 5.7.18 でパスワードを変更する方法

MySQL 5.7.18 でパスワードを変更する方法: 1. まずMySQLサーバーをシャットダウン...

Vue でよく使われる高階関数と包括的な例

1. 配列のよく使われる高階関数配列があり、その配列に対して次の操作を実行したいとします。 100 ...