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 はバージョン番号を非表示にする実稼働環境では、セキュリティ上の脆弱性の漏洩を避けるために...

Vue3 のリアクティブ関数 toRef 関数 ref 関数の紹介

目次リアクティブ機能使用法: toRef 関数 (理解するだけ)使用法: ref関数レスポンシブデー...

Linux の MySQL でリモート接続を承認する方法

注意: 他のマシン (IP) は、承認なしではクライアント経由で MySQL データベースに接続でき...

VueはExcelデータをエクスポートするパブリック関数メソッドをカプセル化します

vue+element UI は Excel データをエクスポートするためのパブリック関数をカプセル...

ウェブサイトのパフォーマンス: 画像とCookieの最適化、モバイルアプリケーションの最適化

前のセクションでは、コンテンツ、サーバー、JavaScript、CSS など、Web サイトのパフォ...

Vue は Ctrip のカルーセル効果を模倣します (スライディング カルーセル、以下は高度に適応)

まずケースを見てみましょう。vue+swiper を使用して実装します。スライドの高さが異なる場合、...

MySQLが中国語の文字を挿入する問題を永久に解決するコツを教えます

目次序文最初のステップ:ステップ2: このmy.iniを変更する要約する序文問題の説明:不正な文字列...

ローカル Docker に Postgres 12 + pgadmin をインストールする方法 (Apple M1 をサポート)

目次導入Intel CPUをサポートApple M1のサポートテスト導入このプロジェクトでは最近、P...

HTML タグ マーキーを使用してスクロール効果を実現する簡単な方法 (必読)

ページの自動スクロール効果は JavaScript で実現できますが、今日偶然、JS 制御なしでさま...

NFS サーバーの原理と、その構築、構成、展開の手順を簡単に分析します。

目次NFS サービスの概要NFS とは何ですか? NFS マウントの原則NFS サーバーはデータ転送...

CSS3 transition-delay属性のデフォルト値が単位なしの0であり無効である問題を解決します

今日は、CSS3 の transition-delay 属性のデフォルト値 0 に単位がないのは無効...

Linux 環境に nginx をインストールするチュートリアル

目次1. 必要な環境をインストールする //gccをインストールする yum で gcc-c++ を...

MySQLのロック機構の詳細な説明

序文データの一貫性と整合性を確保するために、あらゆるデータベースにはロック メカニズムが備わっていま...

Linux 上で Docker コンテナを作成、一覧表示、削除する方法の概要

1. Dockerコンテナを起動する以下のコマンドを使用して新しい Docker コンテナを起動しま...

CSSは固定比率のブロックレベルコンテナを簡単に実装できる

H5 レイアウトを設計する場合、通常はバナーに遭遇することになります。例えば、2:1 で表示したい場...