【MySQL數據類型測試】布爾類型、枚舉類型和集合類型的應用場景詳解(第十節)

MySQL數據庫四種數據類型:布爾類型、微整型、枚舉類型和集合類型,都逐一分析這四種數據類型的特性,以及針對每種數據類型做相應的深入分析和案例測試,挖掘出MySQL手冊沒有詳細寫清楚的部分,相關技術文章可以從數據類型系列第一篇文章MySQL數據庫數據類型之ENUM、SET、BOOL/BOOLEAN、TINYINT特性介紹開始閱讀。
本文內容屬於基於在此之前分享的9篇關於四種數據類型的文章之上,我們結合實際的業務場景和生產環境維護成本等多個角度進行分析,闡述什麼樣的業務場景,適合使用布爾類型、枚舉類型和集合類型?使用這三種數據類型之後,又回給我們帶來哪些麻煩?如何規避這三種數據類型帶來的弊端等問題,將會逐一解答。
(1).布爾類型
MySQL數據庫之數據類型BOOL/BOOLEAN與TINYINT測試總結一文的測試過程和結論,非常清晰地告訴我們:MySQL數據庫的布爾類型BOOL或稱布爾類型BOOLEAN,等同於微整型TINYINT(1)。MySQL數據庫數據類型分類中確實存在布爾類型,但是MySQL數據庫並沒有真正實現布爾類型,而是藉助微整型的方式實現,並且創建數據庫表結構的時候,即使字段定義屬性設置爲布爾類型BOOL或布爾類型BOOLEAN,都會被默認改寫成TINYINT(1)。

建議:
MySQL數據庫產品沒有真正實現對布爾類型的支持,建議大家不要使用MySQL布爾類型BOOL或布爾類型BOOLEAN,而是使用數據庫類型微整型TINYINT替代。
(2).枚舉類型ENUM
對枚舉類型字段存儲數據的數據測試案例分享和總結文章爲MySQL數據庫數據類型之枚舉類型ENUM數據測試總結,對枚舉類型字段進行DDL變更操作支持的案例分享和總結文章爲MySQL數據庫之枚舉數據類型ENUM的DDL變更測試,通過詳盡的測試對比過程,對MySQL枚舉類型的特點非常清晰,我們再簡要綜合地回顧枚舉類型的優缺點:
優點
1)MySQL枚舉類型的枚舉元素允許最大65535個,基本夠絕大多數業務場景使用;
2)引入枚舉類型數據存儲,有利於縮減數據庫存儲數據的容量,尤其能達到減少數據庫瓶頸最大的物理IO,邏輯IO也能減小,提高主機的處理能力;
3)引入枚舉類型數據存儲,有利於簡化工程師的代碼複雜度、工作量,增加代碼的可讀性和可維護性;
4)可以通過枚舉類型元素值訪問數據,也可以根據枚舉類型元素編號進行訪問數據;

缺點
1)MySQL數據庫枚舉類型的引入,可能給軟件程序的版本發佈,存在遺忘數據庫結構變更的隱患;
2)MySQL數據庫枚舉類型字段的元素增加,必須以尾部追加的方式,否則影響數據庫提供數據服務;
3)枚舉類型字段不再需要的元素,也不能進行刪除,否則影響數據庫提供數據服務;
4)MySQL數據庫枚舉類型的字段定義屬性元素值,不能隨意調整其順序,否則影響數據庫提供數據服務;

建議:
MySQL數據庫枚舉類型是一種有應用場景廣泛的數據類型,若是拋開網站程序或軟件版本發佈,可能會導致開發工程師與數據庫維護人員之間沒有配合好的問題,非常推薦大家把枚舉類型引入到生產環境的數據庫應用中,對企業而言也可以起到節省人力、物理等成本。建議大家使用枚舉類型的時候,儘量把可能需要用到的枚舉元素,都寫到MySQL數據庫表字段的定義屬性中,減少出現漏做DDL變更的故障。

(3).集合類型SET
MySQL數據庫數據類型之集合類型SET數據測試總結MySQL數據庫之集合類型SET的DDL變更測試文章,有完整的測試過程,充分總結MySQL數據庫集合類型的優缺點,我們再簡要地回顧集合類型的優缺點。
優點
1)數據庫的數據存儲容量相應縮小,利於減少數據操縱的邏輯IO和物理IO;
2)集合類型的數據讀取方便,可根據字符串值,也可以根據字符串集合的順序編號;
3)集合類型字段的定義屬性維護與其他數據類型類似,並不特殊化;
4)開發工程師,不需要藉助額外的集合元素編碼表或程序中使用編號替代集合的字符串元素,達到減少開發成本、提高代碼的可讀性和可維護性;

缺點
1)集合類型字段的集合元素限制最大爲64個;
2)集合類型字段的定義屬性的集合元素,刪除導致鎖表而影響數據服務提供;
3)集合類型字段的定義屬性的集合元素增加,只能以尾部追加的方式,若是此特性沒有掌握,則會導致數據服務提供受影響;

MySQL數據庫支持集合類型,對解決一些特殊的業務場景提供了非常好的解決方案,經典應用場景案例:
人才招聘網站的用戶,設置工作意向城市一項,則往往會選擇1-3個城市,甚至更多城市,採用集合類型字段作爲數據存儲結果的話,將可以大量簡化程序複雜度,以及大規模降低數據存儲的容量,唯一的遺憾則是集合元素限制爲64個,會導致無法滿足招聘網站後期業務發展需要。

電子商務等行業特點:
1)數據分類的種類較多,往往超過總數64的限制;
2)公司或產品開發維護的技術工程師更迭頻繁;
3)電子商務、招聘網站等行業的產品運營週期長;
4)多數公司的軟件程序版本發佈流程不健全;
5)數據庫維護人員和開發工程師的工作配合,容易出現信息同步不到位或不周全的情況;
6)用戶的數據安全性和正確性,對企業非常重要,往往都是花費較貴的推廣費用吸引而來的;
MySQL數據庫中採用集合類型存儲數據,生產環境的網站程序或軟件版本更新發布時,一旦出現數據庫維護人員沒有優先更新數據庫表字段的定義屬性,則會導致重大的數據丟失事故,給企業造成直接的經濟損失。

網絡遊戲行業的特點:
1)有大量業務是分類不多的數據需要存儲(注:往往是幾個分類,最多不超過30個分類);
2)網絡遊戲行業要求開發成本降低、開發速度快等特點;
3)網絡遊戲公司採用的數據庫服務器的硬件配置差,甚至單硬盤的主機支撐多個數據庫提供數據服務,主機的存儲空間也有限;
4)網絡遊戲產品的生命週期絕大部分不超過5年,一般的網絡遊戲產品運營1年以上就很少再更新軟件的版本;
網絡遊戲產品使用MySQL數據庫集合類型字段存儲業務數據,是非常值得推薦的方式,對開發人員而言,跟使用其他數據類型是一樣的,也無額外學習成本,還可以爲企業降低開發成本、硬件資源成本。

(4).總結
系統地分析了布爾類型、枚舉類型、集合類型,MySQL數據庫沒有實現布爾類型,只是藉助微整型TINYINT(1)間接實現,爲此可以理解MySQL數據庫沒有布爾類型;集合類型與枚舉類型,都各自存在一個非常可怕的弊端 — 數據庫結構變更沒有做,網站程序或軟件版本發佈已上線,導致用戶數據丟失的問題,那麼我們不使用枚舉類型或集合類型,能否獲得這2種數據類型的優點,規避這2種數據類型的缺陷,爲此我們各舉一個實際應用案例。
取代集合類型應用場景—求職者工作意向城市
1)創建存儲城市信息的表City(注:假設只有一個字段:城市名稱)

CREATE TABLE city(ID MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
                  City_Name VARCHAR(20) NOT NULL DEFAULT '',
                  PRIMARY KEY(ID),
                  UNIQUE INDEX idx_city_name(City_Name)
                 )ENGINE=InnoDB CHARACTER SET'utf8' COLLATE'utf8_general_ci';

2)創建存儲城市編號與求職者ID編號的對照關係表

CREATE TABLE user_work_city(UID INT UNSIGNED NOT NULL AUTO_INCREMENT,
                  CityID MEDIUMINT NOT NULL DEFAULT 0,
                  PRIMARY KEY(UID,CityID)
                 )ENGINE=InnoDB CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';  

3)寫入幾條測試數據

INSERT INTO city(City_Name) VALUES('上海'),('北京'),('深圳'),('廣州'),('杭州'),('武漢');
INSERT INTO user_work_city(UID,CityID) VALUES(8263638,1),(8263638,3),(8263638,5);
root@localhost : mysqlops 04:09:17> SELECT * FROM city;
+----+-----------+
| ID | City_Name |
+----+-----------+
|  1 | 上海      |
|  2 | 北京      |
|  4 | 廣州      |
|  5 | 杭州      |
|  6 | 武漢      |
|  3 | 深圳      |
+----+-----------+
6 rows in set (0.00 sec)

root@localhost : mysqlops 04:09:28> SELECT * FROM user_work_city;
+---------+--------+
| UID     | CityID |
+---------+--------+
| 8263638 |      1 |
| 8263638 |      3 |
| 8263638 |      5 |
+---------+--------+
3 rows in set (0.00 sec)

4)通過SQL語句獲得求職者意向城市信息

root@localhost : mysqlops 04:09:35> SELECT UC.UID,GROUP_CONCAT(City_Name) FROM city C ,user_work_city UC
    -> WHERE  UC.UID=8263638 AND C.ID=UC.CityID
    -> GROUP BY UC.UID ORDER BY NULL;
+---------+-------------------------+
| UID     | GROUP_CONCAT(City_Name) |
+---------+-------------------------+
| 8263638 | 上海,深圳,杭州          |
+---------+-------------------------+
1 row in set (0.00 sec)

小結:
求職者可挑選工作意向城市列表,可以通過後臺程序進行編輯,並且存儲在City表中,可以任意進行添加、修改、刪除,都不會造成網站程序版本的更新,也不會影響數據庫提供的數據服務,且城市名稱等信息的變更,只要修改City表即可。另外,通過簡便的內連接SQL查詢語句,就可以符合MySQL支持的JOIN連接算法—嵌套循環算法,效率非常高,也不需要程序進行特殊處理,完全可以取代集合類型的作用,唯一遺憾就是需要多寫點代碼。

電子商務行網站的商品分類目錄
1)創建存儲商品分類信息表

CREATE TABLE product_class(ID MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
                          Product_Description VARCHAR(40) NOT NULL DEFAULT '',
                          Parent_Flag TINYINT NOT NULL DEFAULT 0,
                          PRIMARY KEY(ID),
                          UNIQUE INDEX idx_Product_Desc(Product_Description)
                        )ENGINE=InnoDB CHARACTER SET 'utf8' COLLATE'utf8_general_ci';

2)創建存儲商品分類目錄之間的上下級關係表

CREATE TABLE pc_parent_child(ID MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT,
                           Parent_ID MEDIUMINT NOT NULL DEFAULT 0,
                           Child_ID  MEDIUMINT NOT NULL DEFAULT 0,
                           PRIMARY KEY(ID),
                           INDEX idx_pid_cid(Parent_ID,Child_ID)        
                         )ENGINE=InnoDB CHARACTER SET 'utf8' COLLATE'utf8_general_ci';

3)寫入測試數據

INSERT INTO product_class(Product_Description) 
VALUES('大家電'),('平板電視'),('洗衣機'),('冰箱');
INSERT INTO product_class(Product_Description) 
VALUES('生活電器'),('取暖器'),('加溼器'),('淨化器');

INSERT INTO pc_parent_child(Parent_ID,Child_ID)  VALUES(1,2);
INSERT INTO pc_parent_child(Parent_ID,Child_ID)  VALUES(1,3);
INSERT INTO pc_parent_child(Parent_ID,Child_ID)  VALUES(5,8);

4)商品分類數據查詢
商品分類目錄的數據讀取,都是先讀取父節點的信息,再根據父節點信息讀取其下子節點的數據信息。

root@localhost : mysqlops 05:28:41> SELECT M.Product_Description 
    -> FROM product_class M 
    ->       INNER JOIN pc_parent_child N  ON M.ID=N.Child_ID
    -> WHERE N.Parent_ID=1 ;
+---------------------+
| Product_Description |
+---------------------+
| 平板電視            |
| 洗衣機              |
+---------------------+
2 rows in set (0.00 sec)

小結:
若是採用枚舉類型存儲商品分類信息,我們則可以簡便地創建一張表,2個字段即可實現上述的做法,最大的缺陷是子節點升級爲父節點的時候,則需要發佈網站程序與做數據庫結構變更。修改枚舉類型字段的定義屬性,必須以尾部追加的方式,纔不影響數據庫提供的數據服務。使用我們介紹的替代辦法,則需要工程師編寫更多的代碼實現,可以藉助圖形化管理工具輕鬆完成,各自都有優缺點。

一句話總結:任何解決方案,必須從技術、開發成本、維護成本、可靠性等多個角度綜合論證,尋找最適合團隊、業務場景的方案。

《MySQL數據類型測試》一文到現在已經完全結束了,希望這些用心總結的文章能夠真正的幫到各位同仁們。後面會開始更新新專題,感興趣的可以先關注我哦~
點擊查看往期文章

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章