MySQL表設計也是一門技術活

2021-10-10 21:52:43 字數 3131 閱讀 4298

高階技巧

總結參考文件

眾所周知,好的表設計能讓後續的開發事半功倍,接下來給大家分享一些表設計的技巧。

這個算是老生常談了,這裡簡單的提一下,簡單的原則是都滿足需求的情況下,儲存所需的位元組數越小的字段型別越好

越小則空間占用越小,在查詢時進行的比較操作越快、索引占用的儲存空間也越少,在乙個資料頁內就可以放下更多的記錄,從而減少磁碟i/o帶來的效能損耗,也就意味著可以把更多的資料頁快取在記憶體中,從而加快讀寫效率。

這個建議對於表的主鍵來說更加適用,因為不僅是聚簇索引中會儲存主鍵值,其他所有的二級索引的節點處都會儲存乙份記錄的主鍵值,如果主鍵適用更小的資料型別,也就意味著節省更多的儲存空間和更高效的i/o。

這個是比較容易忽略的點,我見過太多varcahr(255),這種設計是不合適的,應該選擇滿足需求的盡可能小的長度限制,比如姓名一般就20,然後前端做限制。當然具體情況具體分析。

關於這點的權威介紹我暫時沒有找到,找到後會更新到部落格中。但是存在即合理,如果限制沒有用的話,mysql也沒必要做這個功能了。

拓展:innodb引擎對每張表一行的資料大小限制為65535個位元組,也就是說一張表所有欄位的長度加起來不能超過65535個位元組。其中varchar等變長型別欄位還需要兩個位元組來儲存資料實際長度,可空字段需要乙個位元位記錄是否為空。

另外textblob型別的字段是單獨儲存的,所以不會影響所在表的行資料大小,即當一張表其他字段已經占用了65535位元組,你還可以繼續加textblob型別的字段。這也解釋了為什麼textblob字段查詢效率低。

還有就是innodb對於4kb,8kb,16kb(預設)和32kbinnodb_page_size設定,將行大小(用於資料頁中本地儲存的資料)限制為略小於資料頁的一半 ,而對於64kb頁面,則限制為略小於16kb。

為什麼行大小限制為略小於資料頁的一半?這裡簡單解釋一下,為了確保查詢效率,mysql規定每個資料頁至少儲存兩條記錄,每個資料頁除了儲存資料記錄外,還會一百多個位元組的空間儲存一些諸如file headerpage header等資訊。(這塊比較底層了,沒接觸過的話就知道有這麼個事情就行)

關於行大小限制等詳細說明,請參見:mysql官方文件-行大小限制

這裡我直接通過我接手的乙個實際場景來說明吧。

我們有個工單模組,其中工單有個狀態status字段,他以前是用的varchar(10),存的值諸如init、ing、finish、pause、cancel、expire之類的。我見過很多這麼設計這種型別的字段的,這種設計是不可取的。

比較合理的設計是用tinyint(1),如果狀態數量較多則適當增加長度限制。具體取值也很有講究,我的設計:

這麼設計的好處就不用多說了吧?這種業務肯定會有諸如查詢某某未完成的工單、查詢某某完成的工單,亦或者各種狀態的統計的需求。我這個系統就有一堆這種場景,之前的sql就是各種status in ('ing','pause' ...)之類的,改版後呢?status > 0就行,不論是簡易程度還是效能都不在乙個層次!

樹狀結構的資料也是非常常見的,比如組織架構等,長短編碼這種設計技巧非常適用於這種場景。下面是我的乙個專案中的樹狀結構資料:

這個專案它之前實現樹狀結構是通過乙個parent_id+一張祖先表實現的,parent_id記錄該節點的直接父節點id,祖先表就是記錄某乙個節點的所有父節點。這種設計也是挺low的。。。

改版後,通過長短碼的方式實現,只需要乙個pathparent_path字段即可,實現細節:

表字段資訊如下圖所示:

這種設計的好處也非常明顯,比如:

拓展:還有些高階用法,比如編碼的開頭用不同的字元表示不同的型別,比如a001表示a型別的,b001表示b型別的,這樣在可讀性方面也有很大的提公升。

這個也是我的乙個實際場景,當時是為了做乙個流程的功能,領導說不想用流程引擎,太重了,讓我自己設計乙個。流程可以通過介面配置,要支援分叉流程,即支援不同條件走不同的節點。簡單的流程模板圖如下:

在設計表結構的時候,為了方便後續的業務,所以要能記錄 當前流程的節點數(因為有分叉,且流程模板可以隨時修改,所以每個實際的流程的節點數是不一樣的)、流程當前節點資訊,簡單的話就用兩個字段表示了,但是我用乙個欄位就生動形象的表示了?(不往下看,你會怎麼設計呢?)

我當時是用的varchar(20),取值怎麼取呢?我是通過100000這種二進位制的字串表示的,100000表示該流程有6個節點,當前在第乙個節點。00100表示該流程有5個節點,當前在第三個節點。這個設計沒有太多的實用性或效能提公升,但是卻有較高的可讀性,也算是乙個小設計的吧。

當然這只是一種設計技巧,具體的還得根據實際情況來,說不定這種設計技巧在某種場景下異常好用也說不定呢~

像這種流程肯定也有各種狀態,又可以用上上面所說的列舉型別取值技巧

本文主要是介紹了一些我在表設計時的技巧,暫時只想到這幾種,後續又有好的設計也會更新進來。(記得收藏不迷路哦,嘿嘿)

最後如果覺得寫得還可以的,可以點讚支援一下哦~

1、《mysql是怎樣執行的:從根上理解mysql》

2、mysql官方文件

如何學習一門技術

第一步 what 1 這個技術是什麼,本質是什麼?2 這個技術的核心模組有哪些,核心架構是什麼?3 整體流程,細節流程,核心模組的細節分析 核心原理,核心類,流程圖 第二步 why 1 為什麼要使用,解決什麼問題,是否替代方案?2 版本有哪些,每個版本的新增特性,解決問題?3 優缺點是什麼,與同類技...

如何學習一門技術

這一階段主要是對該技術有乙個整體了解,他所解決的是什麼問題,他的整體結構等.第二個階段,學會基本使用了就要去看官方文件,文件會讓你更加詳細的了解該技術的特性,開乙個demo專案把官方的一些例子都試試.第三個階段,嘗試在一些複雜的專案中使用 非生產專案 使用過程中難免會遇到各種各樣的問題,官方文件和搜...

怎樣快速學會一門技術

前幾天 fork 了 ruby china 的原始碼,面對陌生的 ruby 技術棧,一頭霧水。我 fork 它並不單為了學習,而是要在最短的時間搭建起我腦海中的社群 所以我不可能針對每一門新技術都去買一本書來讀上半個月。我在本機執行起 ruby china,新註冊乙個使用者,發現不能發帖,提示說要註...