定義數據庫,及表的命名規範:前端
1,數據庫,表及字段的命名要遵循可讀性原則, 表意性原則, 長名原則(不盡可能或者不使用縮寫,使用長一些的命名,這樣之後會看起來更明白,可是也不太很是的長)java
通一 主鍵的名稱,好比是 id或者是 _id 等,這樣比較好管理。表裏面的字段命名也不須要帶上表名什麼的。什麼意思就是什麼意思就好,不必搞得這樣子。不過表命名能夠 但是 模塊的名稱 做爲前綴 ,好比有一個 模塊 crm ,那麼 crm 模塊裏面 用到的表是 user ,那麼表名 就起爲 crm_user這樣比較好識別和 管理。程序員
我的認爲儘可能不要使用 uuid 的bigint ,通常的小中型項目,int無符號均可以知足了。算法
對於分佈式的主鍵呢。數據庫
通常都是使用 varchar 的 UUID,這樣比較方便管理和使用對於分佈式來講。編程
可是對於一些對接其餘系統的場景,ID可能會讓你痛不欲生,而洗數據也是體力活兒。若是ID過長極容易產生前端顯示問題,畢竟js的long是15位的。因此實際運用中ID長度也要嚴格把控。因此UUID 才保存爲varchar類型,而不是 bigint 這樣比較方便寫代碼和傳給客戶端,不用進行 類型轉換了。服務器
文/codertom(簡書做者)
原文連接:http://www.jianshu.com/p/a3828b42fce8
著做權歸做者全部,轉載請聯繫做者得到受權,並標註「簡書做者」。網絡
2, 爲表中的字段選擇合適的數據類型: 原則:數據庫設計
當一個列能夠選擇多種數據類型時,應該優先考慮數字類型,其次是日期或二進制類型,最後的字符類型(char 類型 好比 varcahr類型好)分佈式
對於相同級別的數據類型,應該優先選擇佔用空間小的數字類型
如何選擇正確的整數類型?
tinyint 一個字節(無符號是取值範圍 0--255), smallint 兩個字節 , mediumint 三個字節
int 四個字節, bigint 八個字節
如何選擇正確的實數類型?
float 四個字節(不是精確類型) , double 八個字節(不是精確類型),decimal (每四個字節存9個數字,小數點佔一個字節) (精確類型,但是佔用的字節數也會多一些,若是是財務,錢的數據就應該使用這個類型,其餘類型的數據,就能夠用 float類型或者是 double類型了)。
如何選擇 varchar 和 char 類型 ?
varchar 用於存儲變長的字符串,只佔用必要的存儲空間(也就是內容是多少,就佔用多少的空間),
列的最大長度小於255 (字符串長度),則只佔用一個額外字節用於記錄字符串長度。
若是列的最大長度大於255,則只佔用兩個額外的字節用於記錄字符串長度。若是 字符串長度比較長,就應該使用 text 等其餘的 類型進行存儲 。
varchar 長度的選擇問題: 使用最小的符合需求的長度。
若是項目上線後,多人使用的狀況下,若是修改了 varchar 的長度 那麼是會 進行鎖表,那麼會產生比較大的系統性能問題的,致使項目崩掉或者是其餘數據問題,最好不要這麼作。
使用 varchar的場景:
1, 字符串列的最大長度比平均長度大不少
2, 字符串列不多被更新
3,使用了 多字節字符集存儲字符串
char 類型:
char類型 是定長的, 字符串存儲在 char 類型中的列會刪除末尾的空格,
char類型的 最大寬度是 255個類型 。
char類型 適用的 場景:
1,適合存儲 所長度近似的值 (好比手機號,身份證等)
2, char類型適合存儲短字符串(比用 varchar 更加節省空間)
3, char類型適合存儲那些常常被更新的字符串
如何存儲時間類型:
datetime = YYYY-MM-DD HH:MM:SS 格式存儲時間類型
datetime (6) = YYYY-MM-DD HH:MM:SS:微秒的 格式存儲 時間類型
datetime類型和 時區無關,內容並不會隨着時區的變化而變化,佔8個字節
datetime是比較通用型時間類型,通常均可以使用,它表示的時間範圍也是很大的。
timestamp 時間戳,存儲的是 1970年 1月1日 ,到目前的秒數
顯示的是 YYYY-MM-DD HH:MM:SS 格式 的,佔用4個字節,比datetime更加節省空間,但是 timestamp只存儲到 2038年的 時間範圍,並且它的時間顯示依賴於設置的時區,隨着時區的改變而改變 。可是當行修改的時候,能夠自動修改timestamp列的值 .
date 類型,格式送 YYYY-MM-DD ,優勢,佔用的字節數 比使用的字節數,datetime , int 存儲要少,
使用 date 只存儲3個字節 ,存儲範圍也是很大的
使用date類型,還可使用 時間日期的函數進行計算
time類型 格式是 HH:MM:SS 格式 的(能夠指定寬度來存儲微秒的數據)
存儲時間日期的 注意事項:
1,不要使用字符串類型來存儲日期時間類型(日期時間類型好比 字符串類型用的空間小)
2,日期時間類型在進行查找過濾時可使用日期來進行對比
3,日期時間類型有很豐富的函數,能夠方便對其進行日期的計算
4,若是要使用 int類型存儲日期,那就使用 timestamp類型(若是在這個時間範圍內,timestamp存儲其實就是存儲int的,只是顯示的方式仍是之前那個樣子而已)
如何爲 InnoDB選擇主鍵:
主鍵應該儘量的小(能夠提升查詢效率)
主鍵應該是順序增加的(這樣能夠增長插入的效率,減小IO消耗,提升性能)
主鍵能夠和業務主鍵不一樣,爲了保證惟一性,能夠加惟一的索引
明確指定數據列的NOT NULL屬性可以使MySQL在檢索過程當中不用去判斷數據列是不是NULL
儘可能使用 NOT NULL
NULL 類型比較特殊,SQL 難優化。雖然 MySQL NULL類型和 Oracle 的NULL 有差別,會進入索引中,但若是是一個組合索引,那麼這個NULL 類型的字段會極大影響整個索引的效率。此外,NULL 在索引中的處理也是特殊的,也會佔用額外的存放空間。
不少人以爲 NULL 會節省一些空間,因此儘可能讓NULL來達到節省IO的目的,可是大部分時候這會拔苗助長,雖然空間上可能確實有必定節省,卻是帶來了不少其餘的優化問題,不但沒有將IO量省下來,反而加大了SQL的IO量。因此儘可能確保 DEFAULT 值不是 NULL,也是一個很好的表結構設計優化習慣
LOB類型:強烈反對在數據庫中存放 LOB 類型數據,雖然數據庫提供了這樣的功能,但這不是他所擅長的,咱們更應該讓合適的工具作他擅長的事情,才能將其發揮到極致
儘可能使用TIMESTAMP類型,由於其存儲空間只須要 DATETIME 類型的一半。對於只須要精確到某一天的數據類型,建議使用DATE類型,由於他的存儲空間只須要3個字節,比TIMESTAMP還少。不建議經過INT類型類存儲一個unix timestamp 的值,由於這太不直觀,會給維護帶來沒必要要的麻煩,同時還不會帶來任何好處。
非萬不得已不要使用 TEXT 數據類型,其處理方式決定了他的性能要低於char或者是varchar類型的處理。定長字段,建議使用 CHAR 類型,不定長字段儘可能使用 VARCHAR,且僅僅設定適當的最大長度,而不是很是隨意的給一個很大的最大長度限定,由於不一樣的長度範圍,MySQL也會有不同的存儲處理。
.數字類型:非萬不得已不要使用DOUBLE,不只僅只是存儲長度的問題,同時還會存在精確性的問題。一樣,固定精度的小數,也不建議使用DECIMAL,建議乘以固定倍數轉換成整數存儲,能夠大大節省存儲空間,且不會帶來任何附加維護成本。對於整數的存儲,在數據量較大的狀況下,建議區分開 TINYINT / INT / BIGINT 的選擇,由於三者所佔用的存儲空間也有很大的差異,能肯定不會使用負數的字段,建議添加unsigned定義。固然,若是數據量較小的數據庫,也能夠不用嚴格區分三個整數類型。
能夠參考: http://blog.csdn.net/aya19880214/article/details/45871733
BLOB和TEXT類型
它們都是爲存儲大數據而設計的,BLOB是採用二進制/TEXT採用字符存儲。MySQL不能將BLOB和TEXT列所有進行索引(只能作前面某長度的索引,所以在查詢SQL時不能用LIKE前模糊匹配,那樣就走不到索引了),也不能使用這些索引進行排序。
技巧:使用枚舉代替字符串類型,枚舉能夠把一些重複的字符串存儲成一個預約義的集合,MySQL在存儲枚舉時很是緊湊,MySQL在列中保存值爲枚舉中的位置整數。枚舉最很差的是字符串是固定的,添加或刪除必須使用ALTER TABLE。所以對於將來會改變的字符串,使用枚舉不是一個好主意,除非能接受在枚舉末尾添加元素,因爲枚舉有一個映射轉換過程,因此枚舉雖然能減小存儲空間,可是也會增長一些額外開銷。
BLOB和TEXT類型,BLOB以二進制存儲(一、0數據流,搞硬件編程的比較熟悉),TEXT以字符形式存儲,都是用來存儲很大數據的類型,注意,他們也是字符串類型,只是存儲形式不一樣。
BLOB和TEXT類型,在MySQL中會被做爲對象處理,儘可能避免使用。
在使用text和blob字段類型時要注意如下幾點,以便更好的發揮數據庫的性能。
①BLOB和TEXT值也會引發本身的一些問題,特別是執行了大量的刪除或更新操做的時候。刪除這種值會在數據表中留下很大的"空洞",之後填入這些"空洞"的記錄可能長度不一樣,爲了提升性能,建議按期使用 OPTIMIZE TABLE 功能對這類表進行碎片整理.
②使用合成的(synthetic)索引。合成的索引列在某些時候是有用的。一種辦法是根據其它的列的內容創建一個散列值,並把這個值存儲在單獨的數據列中。接下來你就能夠經過檢索散列值找到數據行了。可是,咱們要注意這種技術只能用於精確匹配的查詢(散列值對於相似<或>=等範圍搜索操做符 是沒有用處的)。咱們可使用MD5()函數生成散列值,也可使用SHA1()或CRC32(),或者使用本身的應用程序邏輯來計算散列值。請記住數值型散列值能夠很高效率地存儲。一樣,若是散列算法生成的字符串帶有尾部空格,就不要把它們存儲在CHAR或VARCHAR列中,它們會受到尾部空格去除的影響。
合成的散列索引對於那些BLOB或TEXT數據列特別有用。用散列標識符值查找的速度比搜索BLOB列自己的速度快不少。
③在沒必要要的時候避免檢索大型的BLOB或TEXT值。例如,SELECT *查詢就不是很好的想法,除非你可以肯定做爲約束條件的WHERE子句只會找到所須要的數據行。不然,你可能毫無目的地在網絡上傳輸大量的值。這也是 BLOB或TEXT標識符信息存儲在合成的索引列中對咱們有所幫助的例子。你能夠搜索索引列,決定那些須要的數據行,而後從合格的數據行中檢索BLOB或 TEXT值。
④把BLOB或TEXT列分離到單獨的表中。在某些環境中,若是把這些數據列移動到第二張數據表中,可讓你把原數據表中 的數據列轉換爲固定長度的數據行格式,那麼它就是有意義的。這會減小主表中的碎片,使你獲得固定長度數據行的性能優點。它還使你在主數據表上運行 SELECT *查詢的時候不會經過網絡傳輸大量的BLOB或TEXT值。
還有就是對於 bit 類型的使用 ,若是是 bit(1) 就表明只有一位的數字,不是 0,就是 1 。
這樣子對應java的類型就是 boolean布爾類型,能夠用來進行布爾的判斷。 true表明 1, 0表明 false
好比能夠 直接這樣進行 使用 select * from table where flage=true ; 就能夠查詢出 flage(bit (1) ) =1 的全部數據了。若是是 bit(2) 就表明是2位了,不能存入 1位的,若是輸入 1,那麼默認就會存儲是 01 兩位的。
使用BIT數據類型保存位段值。BIT(M)類型容許存儲M位值。M範圍爲1到64,BIT(1)定義一個了只包含單個比特位的字段, BIT(2)是存儲2個比特位的字段,一直到64位。要指定位值,可使用b'value'符。value是一個用0和1編寫的二進制值。例如,b'111'和b'100000000'分別表示7和128。若是爲BIT(M)列分配的值的長度小於M位,在值的左邊用0填充。例如,爲BIT(6)列分配一個值b'101',其效果與分配b'000101'相同。
MySQL把BIT當作字符串類型, 而不是數據類型。當檢索BIT(1)列的值, 結果是一個字符串且內容是二進制位0或1, 而不是ASCII值」0″或」1″。
一般咱們使用 bit(1) 來表示 布爾類型的,通常也是這樣使用的。
總的來講,進行數據庫表的物理的 表的字段結構進行設計的時候呢,要權衡 好,查詢 的效率問題和 咱們程序員使用的方便的角度。 不要太 追求極端了,要平衡好。並且我的認爲,不要站在 數據庫設計者的角度看問題,應該站在咱們程序員的角度看問題。好比 一些 字段類型,所有都使用 varchar 類型 又如何? 真的就對效率產生很大影響了? 若是效率過低了,能夠進行 索引,或者一些表插入和查詢而已就用用 myisam 存儲引擎, 一些有事物的就用 innodb 等,增長數據庫服務器,服務器的配置的。目前服務器又不貴了。並且 只有項目賺到了錢了,分庫,分表,讀寫分離,分佈式什麼的, 那不是小意思。因此不太在乎,不要太完美,好用纔是王道。提升開發效率纔好,不要讓開發 把至關大的部分的事情 浪費在 數據庫方面去。
其實在開發設置中,仍是結合 實際的狀況來進行,特別是 公司裏面沒有 DBA 的狀況下,對於數據設計來講,固然是 儘可能按照 可使用 數據庫 性能 最優的方式了,,可是實際開發中,咱們爲了開發效率,是能夠 不按照 規定來的,好比 主鍵就使用 varchar ;
設計字段的時候,就是 默承認覺得 null , 由於隨着業務發展,有些字段是能夠爲 null , 這樣若是咱們 設計爲 非 null,咱們不是插入的時候要插入 默認值? 影響開發效率 。。。等等總之,若是 對於中小公司,和 項目狀況來 , 開發效率和後期維護成本纔是王道,,,至於數據庫的設計這塊,不必,也不能有完美的 設計的。 再我看來, 目前出現了那麼多數據庫類型, 數據庫就是 爲了開發和維護服務的,畢竟 咱們是開發人員,不是專業的DBA ,,, 咱們不想 沒事老加班,,爲了 追求所謂的完美,沒意義