例項測試MySQL的enum型別

2022-09-25 14:33:16 字數 3157 閱讀 4139

在開發專案時通常會遇到一些狀態字段,例如訂單的狀態有 待支付、已支付、已關閉、已退款 等,我以前做的專案都是把這些狀態用數字存在資料庫中,然後在 php **中用常量來維護乙份對映表,例如:

const status_pending = 0;

const status_paid = 1;

const status_closed = 2;

const status_refunded = 3;

但是在實際使用過程中發現並不是那麼好用,由於各種原因(追查 bug、臨時的統計需求等)我們常常需要登入到 mysql 伺服器裡手動執行一些 sql 查詢,由於許多表都有狀態字段,寫 sql 時必須對照的 php **裡的對映關係來寫,一不小心還有可能將不同表的狀態數字弄混導致大問題。

於是我在新專案中準備使用 mysql 的 enum 型別來儲存各種狀態,在使用過程中發現如果在 lar**el 的 migration 檔案中對使用了 enum 型別的表做變更(即使是變更非 enum 型別的字段)都會報錯

[doctrine\dbal\

unknown database type enum requested, doctrine\dbal\platforms\mysql57platform may not support it.

搜尋了一下,發現是 doctrine 不支援 mysql 的 enum,該文中列舉了 enum 的 3 個缺點:

新增 enum 值的時候需要重建整個表,當資料量大的時候可能需要耗費數小時。

enum 值的排序規則是按建立表結構時指定的順序,而非字面值的大小。

依賴 mysql 對 enum 值的校驗並不是非常必要,在預設配置下插入非法值最終會變成空值。

根據新專案的實際情況,不太可能出現需要對狀態字段做排序的需求,即使有我們可以在設計表結構的時候就定好順序,因此缺點 2 可以忽略;而缺點 3 則可以通過**規範、插入/更新前校驗等方式來規避;至於缺點 1,我們需要做一些測試。

測試準備#

首先建立乙個表:

create table `enum_tests` (

`id` int(10) unsigned not null auto_increment,

`status` enum('pending','succeswww.cppcns.coms','closed') collate utf8mb4_unicode_ci not null,

primary key (`id`)

) engine=innodb default charset=utf8mb4 cowww.cppcns.comllate=utf8mb4_unicode_ci;

然後插入 100w 條資料:

$count = 1000000;

$bulk = 1000;

$data = ;

foreach (['pending', 'success', 'closed'] as $status)

}for ($i = 0; $i < $count; $i += $bulk)

測試過程#

測試1#

在 enum 值列表最後新增乙個值 refunded

alter table `enum_tests` change `status` `status` enum('pending','success','closed','refunded') character set utf8mb4 collate utf8mb4_unicode_ci not null;

輸出:query ok, 0 rows affected (0.04 sec)

records: 0 duplicates: 0 warnings: 0

結論:在末尾追加 enum 值時幾乎沒有成本。

測試 2:#

刪除剛剛新增的值 refunded

alter table `enum_tests` change `status` `status` enum('pending','success','closed') character set utf8mb4 collate utf8mb4_unicode_ci not null;

輸出:query ok, 1000000 rows affected (5.93 sec)

records: 1000000 duplicates: 0 warnings: 0

結論:刪除乙個沒有用過的 enum 值仍需全表掃瞄,成本較高,但還在可接受範圍內。

測試 3:#

將 refunded 插入到值列表中間而非末尾

alter table `enum_tests` change `status` `status` enum('pending','success','refunded', 'closed') character set utf8mb4 collate utf8mb4_unicode_ci not null;

輸出:query ok, 1000000 rows affected (6.00 sec)

records: 1000000 duplicates: 0 warnings: 0

結論:在原 enum 值列表中間新增值需要全表掃瞄並更新,成本較高。

測試 4:#

刪除值列表中間的值

alter table `enum_tests` change `statujooukyubvs` `status` enum('pending','success','closed') character set utf8mb4 collate utf8mb4_unicode_ci not null;

輸出:query ok, 1000000 rows affected (4.23 sec)

records: 1000000 duplicates: 0 warnings: 0

結論:需全表掃瞄,成本較高。

測試 5:#

給 status 字段新增索引後再執行上述測試

alter table `enum_tests` add index(`status`);

發現測試 2-4 的耗時反而有所增加,應該是同時需要更新索引導致的。

結語:#

對於我的新專案來說只會出現新增 enum 值的情況,即使將來有個別狀態廢棄不用也不需要去調整 enum 的值列表,因此決定在專案中引入 enum 型別作為儲存狀態的資料型別。

本文標題: 例項測試mysql的enum型別

本文位址: /shujuku/mysql/212563.html

enum列舉類使用例項

package com.elk.wsl.enums author 胖子不胖 description 使用與碼值的轉換 date created in 21 26 2019 2 18 modified by public enum color public string getenglish publ...

mysql基準測試例項 mysql基準測試

toc 單位時間內所處理的事務數 tps 單位時間內所處理的查詢數 qps 響應時間 平均響應時間,最小響應時間,最大響應時間,各時間所佔百分比 併發量 同時處理的查詢請求的數量 併發量不等於連線數 正在工作的併發的操作或同時工作的數量 工具 mysqlslap mysql自帶的 特點 可以模擬伺服...

python的列舉類 Enum

列舉 from enum import enum,unique 1 預設列舉類 month enum month jan feb mar for name,member in month.members items print name,member,member.value value屬性是自動賦...