<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
介紹了MySQL的常用資料型別的基本特性,以及資料型別的選擇優化。
MySQL資料型別是定義列中可以儲存什麼資料以及該資料實際怎樣儲存的基本規則,正確的選擇資料庫欄位的欄位型別對於資料庫效能有很大的影響。
整數型別有五種:TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT,分別使用1、2、3、4、8位元組(8、16、24、32、64位元)的儲存空間。
可以儲存的值的範圍從-2^(N-1)到2^(N-1)-1,其中N是儲存空間的位數,比如TINYINT,它的儲存範圍就是-128-127。
所有的整數型別都預設是有符號數,即可正可負。所有的整數型別都可以設定unsigned屬性,這表示將該整數位段無符號化,即不允許負值,這種操作大致可以使正數的上限提高一倍,例如TINYINT,unsigned可以儲存的範圍是0-255。
有符號數和無符號數,使用相同的儲存空間,具有相同的效能,因此可以根據實際情況選擇。但請注意,MySQL資料庫中unsigned數的操作結果都是unsigned的,因此如果執行了計算,並且結果是負數,那麼最終結果將難以預測,慎用unsigned。
和整數的型別無關的是,整數的計算一般使用有64位元的BIGINT整數,即使在32位元的環境中即是如此。
MySQL可以為整數指定寬度,例如int(1),但這對大多數應用都是無意義的:它不會限制值的合法範圍,只是規定了MySQL的一些互動工具如MySQL命令使用者端)顯示字元的個數,而不是指定的儲存大小。int(1)和int(10)對儲存和計算來說是相同的,但這個規則只適用於整數型別而不適用於varchar和char型別。
實數就是帶有小數部分的數位,然而它們不止是為了儲存小數部分,也可以使用DECIMAL儲存比BIGINT還大的整數。實數型別有三種:FLOAT、DOUBLE、DECIMAL。
實數都可以指定精度,例如DECIMAL(18,9),這表示值儲存的有效位數為18,並且小數點後可以儲存的位數為9,因此整數部分的位數同樣也是9。MySQL 在儲存值時執行舍入,因此如果將 89.0009 插入FLOAT(6,3) 列,則近似結果為 89.001。
MySQL既支援精確型別,也支援不精確型別。FLOAT和DOUBLE型別支援使用標準的浮點運算進行近似計算,稱為浮點數,FLOAT固定佔4個位元組,DOUBLE固定佔8個位元組,精度更高。和整數型別一樣,浮點只能選擇儲存型別,在計算時,MYSQL5使用DOUBLE作為內部浮點計算的型別。
DECIMAL型別則用於儲存精確的小數,在MYSQL5.0以及更高的版本中,DECIMAL型別支援精確計算。DECIMAL 的最大允許65個數位。DECIMAL列使用二進位制格式進行儲存,MYSQL5.0和更高版本中,會將數位打包儲存到一個二進位制字串中:每個值的小數點佔據一個位元組,每個值的整數和小數部分的儲存要求分別確定,每9個十進位制的數位被打包為4個位元組,剩餘的需要另外打包:
剩下的數位 | 所需位元組數 |
---|---|
0 | 0 |
1-2 | 1 |
3-4 | 2 |
5-6 | 3 |
7-9 | 4 |
例如,DECIMAL (18, 9)小數點兩邊都有9位數,因此兩邊都需要4個位元組,另外小數點本身佔一個位元組,一共需要九個位元組。
CPU不支援DECIMAL的精確計算,精確計算是MySQL伺服器自身實現的,因此需要額外的的空間和計算開銷。CPU直接支援浮點運算,所以浮點運算更快,所以儘量只在需要對小數進行精確計算時使用DECIMAL型別(如與錢相關的資料)。
在資料量比較大的時候,可考慮使用BIGINT代替DECIMAL,此時只需根據小數位數乘以相應的倍數即可。比如,如果儲存的財務資料精確到萬分之一時,可以把所有的金額乘以一百萬,然後將結果存入BIGINT裡,這樣就可以避免浮點儲存計算不準確和DECIMAL精度計算代價高的問題。
MySQL支援多種字串型別,主要的有:VARCHAR、CHAR、BLOB、TEXT、ENUM等。
VARCHAR和CHAR是兩種最主要的資料型別,但是不同的儲存引擎會將這兩種資料型別以不同的樣式存入磁碟和記憶體中,下面是InnoDB或者MyISAM儲存引擎中VARCHAR和CHAR的介紹。
VARCHAR型別:
CHAR型別:
如下案例:
CREATE TABLE test(a VARCHAR(4), b CHAR(4)); INSERT INTO test VALUES ('ab ', 'ab '); SELECT CONCAT(a, '+'), CONCAT(b, '+') FROM test;
結果如下:
另外,資料如何儲存取決於儲存引擎,比如Memeory引擎只支援定長的行,即使有變長欄位,也會根據最大長度分配空間。但是對於填充和擷取空格的行為在不同的儲存引擎都是一樣的,因為這是在MySQL伺服器進行處理的。
另外,雖然VARCHAR(5)和VARCHAR(200)儲存"hello"的磁碟空間開銷是一樣的,然是使用更短的列仍然有很大的優勢。因為更長的列會消耗更多的記憶體,因為mysql通常會分配固定大小的記憶體塊來儲存內部值,尤其是使用記憶體臨時表來進行排序或操作時特別糟糕,在利用磁碟臨時表進行排序時也同樣糟糕。因此最好的策略是隻分配真正需要的空間。
MySQL4.1版本之前,varchar(n),指的是n個位元組,如果存放UTF8型別字元時,只能存n/3個字元(每個字元佔3個位元組)。
MySQL4.1版本開始,varchar(n),指的是n個字元,無論存放的是數位、字母還是漢字,都可以存放3個,但是位元組數不能超過最大限制。
首先,一張表中所有欄位的長度總和不超過65535位元組。
CHAR型別最大長度為255個字元(字元數量,而非位元組數量)。
而VARCHAR型別的最大長度則是可變的,需要計算,VARCHAR的最大長度還與字元集有關。如果一張表有VARCHAR和CHAR型別的欄位分別一個,採用utf8mb4編碼(一個字元最多佔4個位元組),那麼所有欄位一共最多65535/4=16383.75=16383個字元長度,如果其中CHAR型別的欄位長度為5,那麼VARCHAR型別的最大長度則是16378。
Binary和VarBinary用於儲存二進位制字串,儲存的是位元組碼而非字元。
MySQL在填充Binary時用的是 (零位元組)而不是空格,在檢索時也不會去掉填充值(這是特別需要注意的)。
MySQL在比較Binary字串時,每次按一個位元組,並且是根據該位元組的數值進行比較;因此二進位制比較比字串的比較快。
BLOB和TEXT都是為儲存很大的資料而設計的,分別採用二進位制和字元方式儲存,都是變長字串型別。
實際上它們屬於不同的資料型別家族:字元型別是TINYTEXT、SMALLTEXT、TEXT、MEDIUMTEXT、LONGTEXT,對應的二進位制型別是 TINYBLOB、SMALLBLOB、BLOB、MEDIUMBLOB、LONGBLOB。BLOB和SMALLBLOB是同義詞,TEXT和SMALLTEXT是同義詞。
與其他型別不同,每個BLOB和TEXT值會被當成獨立的物件物件。當資料很大時,InnoDB會專門使用“外部”儲存區域儲存,此時每個值在行內需要1~4個位元組儲存一個指標,然後在外部儲存區域儲存實際的值。
BLOB和TEXT家族的僅有不同是BLOB型別儲存的是二進位制資料,沒有排序規則或者字元集,而TEXT型別有字元集和排序規則。
MySQL只會對BLOB和TEXT列中最前max_sort_length位元組進行排序,而不是整個字串。如果只排序前面一小部分字元,則可以減小max_sort_length的值,或者使用order by substring(列名,length)。
MYSQL不能將BLOB和TEXT列全部長度字串進行索引,也不能用這些索引消除排序。
有時可以使用ENUM代替常用的字串型別。列舉列可以把一些不重複的字串儲存成一個預定義的集合。
ENUM的儲存非常緊湊,會根據列表值的數量壓縮到一個或兩個位元組中。
ENUM在內部會將每個值在列表中的位置儲存為整數,並且在表的.frm檔案中儲存“數位-字串”對映關係的“查詢表”。
如下案例:
-- 建立表 CREATE TABLE enum_test( e enum('fish','apple','dog') NOT NULL ) -- 插入列舉資料 INSERT INTO enum_test (e) VALUES('fish'),('dog'),('apple');
測試實際儲存的是數位:
select e+0 from enum_test;
結果如下:
列舉欄位支援同時採用字串和數值進行判斷和計算,如上面的sql,比如和數值型別進行比較。採用數值時,使用的列舉欄位的排序值,排序值從1開始!
需要注意的是,列舉欄位是按照內部儲存的整數而不是定義的字串進行排序的!
一種繞過這種限制的方式是按照需要的順序來定義列舉列的值,另外也可以使用FIELD()函數顯式的指定排序順序,但這會導致MySQL無法利用索引消除排序。
列舉的字串列表是固定的,新增或者刪除列舉字串必須使用ALTER TABLE這樣的DDL語句,因此對於未來可能會改變的字串,使用列舉不是一個好主意。
由於MySQL把每一個列舉值儲存為整數,在檢索時必須進行額外的查詢才能轉換為字串,所以會有一定的開銷。
MySQL有很多日期和時間型別,比如DATE、DATETIME、TIMESTAMP、TIME、YEAR。可以儲存的最小時間粒度是秒。
DATETIME型別能儲存大範圍的值,從1001年~9999年,精度為秒,佔8個位元組的長度。它將時間格式封裝為YYYYMMDDHHMMSS的整數中,與時區無關。預設情況下,MySQL以一種可排序的格式顯示DATETIME值,比如“2019-11-12 13:56:45”。
TIMESTAMP型別的儲存的是1970年1月1日午夜以來的秒數(格林威治標準時間),只使用了4個位元組的儲存空間,因此它的範圍比DATETIME小得多:1970年~2038年。
TIMESTAMP列會預設設定為Not null屬性,所以在插入資料時,若不給值就會預設為當前時間戳。
目前,MySQL沒有提供合適的資料型別以儲存比秒更小粒度的日期和時間格式,但可以使用其他方法,比如使用BIGINT儲存微秒級別的時間戳,比如用DOUBLE儲存秒之後的小數部分。
MySQL的所有位型別,不管底層儲存和處理方式如何,從技術上來說都是字串型別。常見位資料型別是BIT和SET。
在MySQL5.0之前,BIT是TINYINT的同義詞,但5.0之後有了新的含義。
BIT(1)表示一個包含單個位的欄位,BIT(2)則表示兩個位的欄位,最大長度為64位元。
不同的儲存引擎對BIT 有不同的儲存方式。MyISAM會打包儲存所有BIT列,比如17個單獨的BIT列只需要17位儲存,只需要3個位元組的空間。而Memory和InnoDB等儲存引擎,則是為每個BIT列使用一個足夠儲存的最小整數型別來存放,所以不能節省儲存空間。
注意,MySQL將BIT當作字串型別,而不是數位型別。如果檢索BIT(1)的值時,結果是一個包含二進位制0或1的字串,而不是ASCII碼的“0”或“1”。然而,在數位上下文中檢索時,結果將是字串轉換成的數位。比如儲存一個值為b‘00111001’(等於十進位制57)到BIT(8)的列並直接檢索它,得到的內容是“00111001,而如果檢索的內容是“列+0”,那麼得到的值是57。
如下案例:
CREATE TABLE `bits` ( `bitss` bit(8) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; INSERT INTO `bits`(`bitss`) VALUES (b'00111001'); INSERT INTO `bits`(`bitss`) VALUES (b'111');
使用如下查詢:
select bitss,bitss+0 from bits
結果如下:
位型別的常見用法是:如果需要位一條資料儲存許多true/false值,則可合併這些列到一個SET資料型別的列。
MySQL支援的資料型別非常多,選擇正確的資料型別對於獲得高效能至關重要,不管儲存哪種資料型別,下面幾個簡單的原則都有助於做出更好的選擇!
IPv4地址經常被人用varchar(15)來儲存,但是它實際上是一個32位元無符號的整數,不是字串,小數點將地址分四段的表示方式只是為了讓人容易閱讀,所以應該用無符號整型來儲存IP地址(如果不使用無符號INT,則長度不夠),MYSQL用INET_ATON() 和INET_NTOA()用於這兩種表示轉換。
select inet_aton(ip) from xxx;
select inet_ntoa(intip) from xxx;
到此這篇關於深入理解MySQL資料型別的選擇優化的文章就介紹到這了,更多相關MySQL資料選擇優化內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45