Mysql數據類型與選擇規則(mysql5.7)

概述

基於mysql5.7。
mysql數據類型大致可以分爲四類:數值型、字符串型、日期和時間類型、空間類型。常用的如數值型的tinyint、int、bigint,字符串型的char、varchar、text,日期型的date、datetime、timestemp等,詳細見下圖:
在這裏插入圖片描述

詳細分析

上表的的一些類型存儲規則依賴存儲引擎(MyISAM、InnoDB、NDB等)和編碼(GBK、UTF8等),(不過大分部用不到,可以先不瞭解),具體可以看看官方文檔

1. 整數型
對於 int、tinyint、bigint、smallint,mysql允許用unsigned 和 zerofill關鍵字修飾。

UNSIGNED修飾符規定字段只保存正值,即無符號,而mysql字段默認是有符號的。因爲不需要保存數字的正、負符號,可以在儲時節約一個"位"的空間(即翻一倍)。從而增大這個字段可以存儲的值的範圍。注意這個修飾符要緊跟在數值類型後面;
!!!
ZEROFILL 修飾符規定 0(不是空格)可以用來真補輸出的值。使用這個修飾符可以阻止 MySQL數據庫存儲負值,如果某列設置爲zerofill,那它自動就unsigned。

2. char與varchar

char與varchar都是用來存儲字符數據的,其存儲規則依賴存儲引擎(MyISAM、InnoDB、NDB、BDB、Memory等)和編碼(GBK、UTF8系列等)。

對於char
char(m)表示最多插入m個字符,不管是英文字母,還是數字或漢字,不足m則在尾部空格填充,除非開啓 PAD_CHAR_TO_FULL_LENGTH。

對於varchar
varchar(m)表示最多插入m個字符,不管是英文字母,還是數字或漢字,不足m不需要空格填充,但varchar需要額外空間記錄存入字符串的長度,m<255,花費1byte,m>255,花費2byte。
在這裏插入圖片描述
注意
(1)m表示m個字符,而非字節。
在mysql4.0版本以下,varchar(20),指的是20字節,如果存放UTF8漢字時,只能存6個(每個漢字3字節)。

5.0版本以上,varchar(20),指的是20字符,無論存放的是數字、字母還是UTF8漢字(每個漢字3字節),都可以存放20個,最大大小是65532字節 ,結束位佔去了2個字節。

(2)編碼的影響
GBK:漢字佔2個字節,最大長度不能超過32766;
UTF8:漢字佔3個字節,最大長度不能超過21845。

(3)行長度限制
MySQL要求一個行的定義長度不能超過65535。若定義的表長度超過這個值,則提示轉化爲TEXT or BLOB型。

ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs。

二者性能與選擇
性能:char直接存儲,不足補空格就好,操作簡單,檢索效率高。
varchar在存儲時需要計算其長度,較慢,但節省存儲空間。

選擇
根據字符的長度來判斷,是考慮其長度的是否相近來確定選擇char還是varchar,如何字段的長度基本都是一樣或者其長度總是近似的可以選用char。
不過即使使用Varchar數據類型,也不能夠太過於慷慨! 比如你只使用到90個字符,VARCHAR(100)與VARCHAR(200)真的相同嗎?結果是否定的。雖然他們用來存儲90個字符的數據,其存儲空間相同。但是對於內存的消耗是不同的。

VARCHAR和TEXT、BlOB類型的區別

VARCHAR,BLOB和TEXT類型是變長類型,對於其存儲需求取決於列值的實際長度(在前面的表格中用L表示),而不是取決於類型的最大可能尺寸。例如,一個VARCHAR(10)列能保存最大長度爲10個字符的一個字符串,實際的存儲需要是字符串的長度
,加上1個字節以記錄字符串的長度。對於字符串’abcd’,L是4而存儲要求是5個字節。
  
  BLOB和TEXT類型需要1,2,3或4個字節來記錄列值的長度,這取決於類型的最大可能長度。VARCHAR需要定義大小,有65535字節的最大限制;TEXT則不需要。如果你把一個超過列類型最大長度的值賦給一個BLOB或TEXT列,值被截斷以適合它。
  
一個BLOB是一個能保存可變數量的數據的二進制的大對象。4個BLOB類型TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB僅僅在他們能保存值的最大長度方面有所不同。

BLOB
可以儲存圖片,TEXT不行,TEXT只能儲存純文本文件。4個TEXT類型TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT對應於4個BLOB類型,並且有同樣的最大長度和存儲需求。在BLOB和TEXT類型之間的唯一差別是對BLOB值的排序和比較以大小寫敏感方式執行,而對TEXT值是大小寫不敏感的。換句話說,一個TEXT是一個大小寫不敏感的BLOB。

char和varchar可以有默認值,text不能指定默認值。

性能上char>varchar>text。

3. 日期型數據

日期時間類型在MySQL 5.6.4之前創建的表所需的存儲與從5.6.4創建的表不同。這是由於5.6.4中的更改允許這些類型具有小數部分,這需要0到3個字節。
在這裏插入圖片描述mysql5.6.5之前只有timestemp可以自動更新爲當前時間,但6.5及以上datetime也可以和timestemp一樣了。

CREATE TABLE t1 (
  ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  dt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  name CHAR(5)
);

即默認當前時間同時行數據(name)變化時,dt和ts自動更新。

常見類型的選擇

姓名:char(20)
價格:DECIMAL(7, 3)
產品序列號:unsigned SMALLINT(5)
文章內容: TEXT
手機號:char(11)
自增主鍵:unsigned bigint(20)
MD5: CHAR(32)
ip: char(15)或者借用inet_aton/inet_ntoa函數
time: int(10)
email:char(32)

合理的選擇數據類型

  • 選擇合理範圍內最小的

    我們應該選擇最小的數據範圍,因爲這樣可以大大減少磁盤空間及磁盤I/0讀寫開銷,減少內存佔用,減少CPU的佔用率。

  • 選擇相對簡單的數據類型

    數字類型相對字符串類型要簡單的多,尤其是在比較運算時,所以我們應該選擇最簡單的數據類型,比如說在保存時間時,因爲PHP可以良好的處理LINUX時間戳所以我們可以將日期存爲int(10)要方便、合適、快速的多。

    但是,工作中隨着項目越做越多,業務邏輯的處理越來越難以後,我發現時間類型還是用時間類型本身的字段類型要好一些,因爲mysql有着豐富的時間函數供我使用,方便我完成很多與時間相關的邏輯,比如月排行榜,周排行榜,當日熱門,生日多少天等等邏輯

  • 不要使用null

    爲什麼這麼說呢,因爲MYSQL對NULL字段索引優化不佳,增加更多的計算難度,同時在保存與處理NULL類形時,也會做更多的工作,所以從效率上來說,不建議用過多的NULL。有些值他確實有可能沒有值,怎麼辦呢?解決方法是數值弄用整數0,字符串用空來定義默認值即可。

  • 字符串類型的使用

    字符串數據類型是一個萬能數據類型,可以儲存數值、字符串、日期等。
    保存數值類型最好不要用字符串數據類型,這樣存儲的空間顯然是會更大,而且在排序時字符串的9是大於22的,其實如果進行運算時mysql會將字符串轉換爲數值類型,大大降低效果,而且這種轉換是不會走原有的索引的。
    如果明確數據在一個完整的集合中如男,女,那麼可以使用set或enum數據類型,這種數據類型在運算及儲存時以數值方式操作,所以效率要比字符串更好,同時空間佔用更少。

  • VARCHAR與CHAR

    VARCHAR是可變長度字符串類型,那麼即然長度是可變的就會使用1,2個字節來保存字符的長度,如果長度在255內使用1個字節來保存字符長度,否則使用2個字符來保存長度。由於varchar是根據儲存的值來保存數據,所以可以大大節約磁盤空間。
    如果數據經常被執行更新操作,由於VARCHAR是根據內容來進行儲存的,所以mysql將做更多的工作來完成更新操作,如果新數據長度大於老數據長度一些存儲引擎會進行拆分操作處理。同時varchar會完全保留內部所有數據,最典型的說明就是尾部的空格。
    CHAR固定長度的字符串保存類型,CHAR會去掉尾部的空格。在數據長度相近時使用char類型比較合適,比如md5加密的密碼用戶名等。
    如果數據經常進行更新修改操作,那麼CHAR更好些,因爲char長度固定,性能上要快。

  • 數值類型的選擇

    數值數據類型要比字符串執行更快,區間小的數據類型佔用空間更少,處理速度更快,如tinyint可比bigint要快的多

    選擇數據類型時要考慮內容長度,比如是保存毫米單位還是米而選擇不同的數值類型

  • 整數

    整數類型很多比如tinyint、int、smallint、bigint等,那麼我們要根據自己需要存儲的數據長度決定使用的類型,同時tinyint(10)與tinyint(100)在儲存與計算上並無任何差別,區別只是顯示層面上,但是我們也要選擇適合合適的數據類型長度。可以通過指定zerofill屬性查看顯示時區別。

  • 浮點數與精度數值

    浮點數float在儲存空間及運行效率上要優於精度數值類型decimal,但float與double會有舍入錯誤而decimal則可以提供更加準確的小數級精確運算不會有錯誤產生計算更精確,適用於金融類型數據的存儲。

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