MySQL面试 (一) 数据类型
文章目錄
- mysql數(shù)據(jù)類型匯總
- 1、整數(shù)類型
- 2、浮點(diǎn)數(shù)類型
- 3、字符串類型
- 4、枚舉類型(ENUM)
- 5、日期和時(shí)間類型
- 面試題
- 1. int(10) 和 bigint(10)能存儲(chǔ)的數(shù)據(jù)大小一樣嗎?
- 2. varchar存儲(chǔ)規(guī)則
- 3. MySQL中varchar最大長(zhǎng)度是多少?
- 4. char和varchar有什么區(qū)別?
- 5. Datetime 和 Timestamp 之間抉擇
- 5.1 DateTime 類型沒有時(shí)區(qū)信息
- 5.2 擴(kuò)展:一些關(guān)于 MySQL 時(shí)區(qū)設(shè)置的一個(gè)常用 sql 命令
- 5.3 DateTime 類型耗費(fèi)空間更大
- 5.4 數(shù)值型時(shí)間戳是更好的選擇嗎?
- 5.5 總結(jié)
mysql數(shù)據(jù)類型匯總
| 整數(shù)類型 | tinyInt | 很小的整數(shù)(8位二進(jìn)制) |
| smallint | 小的整數(shù)(16位二進(jìn)制) | |
| mediumint | 中等大小的整數(shù)(24位二進(jìn)制) | |
| int(integer) | 普通大小的整數(shù)(32位二進(jìn)制) | |
| BigInt | 64位 | |
| 浮點(diǎn)數(shù)類型 | float | 單精度浮點(diǎn)數(shù) |
| double | 雙精度浮點(diǎn)數(shù) | |
| decimal(m,d) | 壓縮嚴(yán)格的定點(diǎn)數(shù),共m位,取d位存儲(chǔ)小部分,剩下m-d位存儲(chǔ)整數(shù)部分 | |
| 日期類型 | year | YYYY 1901~2155 |
| time | HH:MM:SS -838:59:59~838:59:59 | |
| date | YYYY-MM-DD 1000-01-01~9999-12-3 | |
| datetime | YYYY-MM-DD HH:MM:SS 1000-01-01 00:00:00~ 9999-12-31 23:59:59 | |
| timestamp | YYYY-MM-DD HH:MM:SS 19700101 00:00:01 UTC~2038-01-19 03:14:07UTC | |
| 文本、二進(jìn)制類型 | CHAR(M) | M為0~255之間的整數(shù) |
| VARCHAR(M) | M為0~65535之間的整數(shù) | |
| TINYBLOB | 允許長(zhǎng)度0~255字節(jié) | |
| BLOB | 允許長(zhǎng)度0~65535字節(jié) | |
| MEDIUMBLOB | 允許長(zhǎng)度0~167772150字節(jié) | |
| LONGBLOB | 允許長(zhǎng)度0~4294967295字節(jié) | |
| TINYTEXT | 允許長(zhǎng)度0~255字節(jié) | |
| TEXT | 允許長(zhǎng)度0~65535字節(jié) | |
| MEDIUMTEXT | 允許長(zhǎng)度0~167772150字節(jié) | |
| LONGTEXT | 允許長(zhǎng)度0~4294967295字節(jié) | |
| VARBINARY(M) | 允許長(zhǎng)度0~M個(gè)字節(jié)的變長(zhǎng)字節(jié)字符串 | |
| BINARY(M) | 允許長(zhǎng)度0~M個(gè)字節(jié)的定長(zhǎng)字節(jié)字符串 |
1、整數(shù)類型
- 包括TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT,分別表示1字節(jié)、2字節(jié)、3字節(jié)、4字節(jié)、8字節(jié)整數(shù)。任何整數(shù)類型都可以加上UNSIGNED屬性,表示數(shù)據(jù)是無符號(hào)的,即非負(fù)整數(shù)。
- 長(zhǎng)度:整數(shù)類型可以被指定長(zhǎng)度,例如:INT(11)表示長(zhǎng)度為11的INT類型。長(zhǎng)度在大多數(shù)場(chǎng)景是沒有意義的,它不會(huì)限制值的合法范圍,只會(huì)影響顯示字符的個(gè)數(shù),而且需要和UNSIGNED ZEROFILL屬性配合使用才有意義。
- 例子:假定類型設(shè)定為INT(5),屬性為UNSIGNED ZEROFILL,如果用戶插入的數(shù)據(jù)為12的話,那么數(shù)據(jù)庫實(shí)際存儲(chǔ)數(shù)據(jù)為00012。
2、浮點(diǎn)數(shù)類型
- 包括FLOAT、DOUBLE、DECIMAL。
- DECIMAL可以用于存儲(chǔ)比BIGINT還大的整型,能存儲(chǔ)精確的小數(shù)。而FLOAT和DOUBLE是有取值范圍的,并支持使用標(biāo)準(zhǔn)的浮點(diǎn)進(jìn)行近似計(jì)算。計(jì)算時(shí)FLOAT和DOUBLE相比DECIMAL效率更高一些,DECIMAL你可以理解成是用字符串進(jìn)行處理。
3、字符串類型
- 包括VARCHAR、CHAR、TEXT、BLOB
- VARCHAR用于存儲(chǔ)可變長(zhǎng)字符串,它比定長(zhǎng)類型更節(jié)省空間。VARCHAR使用額外1或2個(gè)字節(jié)存儲(chǔ)字符串長(zhǎng)度。列長(zhǎng)度小于255字節(jié)時(shí),使用1字節(jié)表示,否則使用2字節(jié)表示。VARCHAR存儲(chǔ)的內(nèi)容超出設(shè)置的長(zhǎng)度時(shí),內(nèi)容會(huì)被截?cái)唷?/strong>
- CHAR是定長(zhǎng)的,根據(jù)定義的字符串長(zhǎng)度分配足夠的空間。CHAR會(huì)根據(jù)需要使用空格進(jìn)行填充方便比較。CHAR適合存儲(chǔ)很短的字符串,或者所有值都接近同一個(gè)長(zhǎng)度。CHAR存儲(chǔ)的內(nèi)容超出設(shè)置的長(zhǎng)度時(shí),內(nèi)容同樣會(huì)被截?cái)唷?/strong>
使用策略:
- VARCHAR是最常見的字符串類型。VARCHAR節(jié)省了存儲(chǔ)空間,所以對(duì)性能也有幫助。但是,由于行是可變的,在UPDATE時(shí)可能使行變得比原來更長(zhǎng),這就導(dǎo)致需要做額外的工作。如果一個(gè)行占用的空間增長(zhǎng),并且在頁內(nèi)沒有更多的空間可以存儲(chǔ),MyISAM會(huì)將行拆成不同的片段存儲(chǔ);InnoDB則需要分裂頁來使行可以放進(jìn)頁內(nèi)。
- 下面這些情況使用VARCHAR是合適的:字符串的最大長(zhǎng)度比平均長(zhǎng)度大很多;列的更新很少,所以碎片不是問題;使用了像UTF-8這樣復(fù)雜的字符集,每個(gè)字符都使用不同的字節(jié)數(shù)進(jìn)行存儲(chǔ)。
- 當(dāng)存儲(chǔ)CHAR值時(shí),MySQL會(huì)刪除所有的末尾空格。CHAR值會(huì)根據(jù)需要采用空格進(jìn)行填充以方便比較。 CHAR適合存儲(chǔ)很短的字符串,或者所有值都接近同一個(gè)長(zhǎng)度,如密碼的MD5值。對(duì)于經(jīng)常變更的數(shù)據(jù),CHAR也比VARCHAR更好,因?yàn)镃HAR不容易產(chǎn)生碎片(行間碎片?)。
4、枚舉類型(ENUM)
把不重復(fù)的數(shù)據(jù)存儲(chǔ)為一個(gè)預(yù)定義的集合。有時(shí)可以使用ENUM代替常用的字符串類型。ENUM存儲(chǔ)非常緊湊,會(huì)把列表值壓縮到一個(gè)或兩個(gè)字節(jié)。ENUM在內(nèi)部存儲(chǔ)時(shí),其實(shí)存的是整數(shù)。盡量避免使用數(shù)字作為ENUM枚舉的常量,因?yàn)槿菀谆靵y。排序是按照內(nèi)部存儲(chǔ)的整數(shù)排序。
5、日期和時(shí)間類型
-
DATETIME: 1. 能夠保存從 1001 年到 9999 年的日期和時(shí)間,精度為秒,使用 8 字節(jié)的存儲(chǔ)空間。 2. 它與時(shí)區(qū)無關(guān)。3. 默認(rèn)情況下,MySQL 以一種可排序的、無歧義的格式顯示 DATETIME 值,例如“2008-01-16 22:37:08”,這是 ANSI 標(biāo)準(zhǔn)定義的日期和時(shí)間表示方法。
-
TIMESTAMP: 和 UNIX 時(shí)間戳相同,保存從 1970 年 1 月 1 日午夜(格林威治時(shí)間)以來的秒數(shù),使用 4 個(gè)字節(jié),只能表示從 1970 年 到 2038 年。 它和時(shí)區(qū)有關(guān),也就是說一個(gè)時(shí)間戳在不同的時(shí)區(qū)所代表的具體時(shí)間是不同的。 MySQL 提供了 FROM_UNIXTIME() 函數(shù)把 UNIX 時(shí)間戳轉(zhuǎn)換為日期,并提供了 UNIX_TIMESTAMP() 函數(shù)把日期轉(zhuǎn)換為 UNIX 時(shí)間戳。
- 默認(rèn)情況下,如果插入時(shí)沒有指定 TIMESTAMP 列的值,會(huì)將這個(gè)值設(shè)置為當(dāng)前時(shí)間。應(yīng)該盡量使用 TIMESTAMP,因?yàn)樗?DATETIME 空間效率更高。
面試題
1. int(10) 和 bigint(10)能存儲(chǔ)的數(shù)據(jù)大小一樣嗎?
不一樣,具體原因如下:
- int 能存儲(chǔ)四字節(jié)有符號(hào)整數(shù)。
- bigint 能存儲(chǔ)八字節(jié)有符號(hào)整數(shù)。
所以能存儲(chǔ)的數(shù)據(jù)大小不一樣,其中的數(shù)字 10 代表的只是數(shù)據(jù)的顯示寬度。
- 顯示寬度指明Mysql最大可能顯示的數(shù)字個(gè)數(shù),數(shù)值的位數(shù)小于指定的寬度時(shí)數(shù)字左邊會(huì)用空格填充,空格不容易看出。
- 如果插入了大于顯示寬度的值,只要該值不超過該類型的取值范圍,數(shù)值依然可以插入且能夠顯示出來。
- 建表的時(shí)候指定 zerofill 選項(xiàng),則不足顯示寬度的部分用 0 填充,如果是 1 會(huì)顯示成 0000000001。
- 如果沒指定顯示寬度, bigint 默認(rèn)寬度是 20 ,int默認(rèn)寬度 11。
- 如果一個(gè)數(shù)據(jù)超過指定的寬度,但是數(shù)據(jù)大小只要不超過數(shù)據(jù)類型的最大值依然可以插入成功。
2. varchar存儲(chǔ)規(guī)則
- 4.0版本以下,varchar(20),指的是20字節(jié),如果存放UTF8漢字時(shí),只能存6個(gè)(每個(gè)漢字3字節(jié))
- 5.0版本以上,varchar(20),指的是20字符,無論存放的是數(shù)字、字母還是UTF8漢字(每個(gè)漢字3字節(jié)),都可以存放20個(gè),最大的大小是65532字節(jié)
3. MySQL中varchar最大長(zhǎng)度是多少?
參考文檔
varchar底層
4. char和varchar有什么區(qū)別?
區(qū)別一,定長(zhǎng)和變長(zhǎng):
char 表示定長(zhǎng),長(zhǎng)度固定;varchar表示變長(zhǎng),即長(zhǎng)度可變。當(dāng)所插入的字符串超出它們的長(zhǎng)度時(shí),視情況來處理,如果是嚴(yán)格模式,則會(huì)拒絕插入并提示錯(cuò)誤信息,如果是寬松模式,則會(huì)截取然后插入。如果插入的字符串長(zhǎng)度小于定義長(zhǎng)度時(shí),則會(huì)以不同的方式來處理,如char(10),表示存儲(chǔ)的是10個(gè)字符,無論你插入的是多少,都是10個(gè),如果少于10個(gè),則用空格填滿。而varchar(10),小于10個(gè)的話,則插入多少個(gè)字符就存多少個(gè)。
varchar怎么知道所存儲(chǔ)字符串的長(zhǎng)度呢?實(shí)際上,對(duì)于varchar字段來說,需要使用一個(gè)(如果字符串長(zhǎng)度小于255)或兩個(gè)字節(jié)(長(zhǎng)度大于255)來存儲(chǔ)字符串的長(zhǎng)度。但是因?yàn)樗枰幸粋€(gè)prefix來表示他具體bytes數(shù)是多少(因?yàn)関archar是變長(zhǎng)的,沒有這個(gè)長(zhǎng)度值他不知道如何讀取數(shù)據(jù))。
區(qū)別之二,存儲(chǔ)的容量不同:
對(duì) char 來說,最多能存放的字符個(gè)數(shù) 255,和編碼無關(guān)。而 varchar 呢,最多能存放 65532 個(gè)字符。VARCHAR 的最大有效長(zhǎng)度由最大行大小和使用的字符集確定。整體最大長(zhǎng)度是 65,532字節(jié)
5. Datetime 和 Timestamp 之間抉擇
Datetime 和 Timestamp 是 MySQL 提供的兩種比較相似的保存時(shí)間的數(shù)據(jù)類型。他們兩者究竟該如何選擇呢?
通常我們都會(huì)首選 Timestamp。 下面說一下為什么這樣做!
5.1 DateTime 類型沒有時(shí)區(qū)信息
DateTime 類型是沒有時(shí)區(qū)信息的(時(shí)區(qū)無關(guān)) ,DateTime 類型保存的時(shí)間都是當(dāng)前會(huì)話所設(shè)置的時(shí)區(qū)對(duì)應(yīng)的時(shí)間。這樣就會(huì)有什么問題呢?當(dāng)你的時(shí)區(qū)更換之后,比如你的服務(wù)器更換地址或者更換客戶端連接時(shí)區(qū)設(shè)置的話,就會(huì)導(dǎo)致你從數(shù)據(jù)庫中讀出的時(shí)間錯(cuò)誤。不要小看這個(gè)問題,很多系統(tǒng)就是因?yàn)檫@個(gè)問題鬧出了很多笑話。
Timestamp 和時(shí)區(qū)有關(guān)。 Timestamp 類型字段的值會(huì)隨著服務(wù)器時(shí)區(qū)的變化而變化,自動(dòng)換算成相應(yīng)的時(shí)間,說簡(jiǎn)單點(diǎn)就是在不同時(shí)區(qū),查詢到同一個(gè)條記錄此字段的值會(huì)不一樣。 下面實(shí)際演示一下! 建表 SQL 語句:
建表SQL語句:
CREATE TABLE `time_zone_test` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`date_time` datetime DEFAULT NULL,`time_stamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;插入數(shù)據(jù)
INSERT INTO time_zone_test(date_time,time_stamp) VALUES(NOW(),NOW());查看數(shù)據(jù)
select date_time,time_stamp from time_zone_test;結(jié)果
修改當(dāng)前會(huì)話的時(shí)區(qū)
set time_zone = '+10:00'再次查看數(shù)據(jù)
5.2 擴(kuò)展:一些關(guān)于 MySQL 時(shí)區(qū)設(shè)置的一個(gè)常用 sql 命令
# 查看當(dāng)前會(huì)話時(shí)區(qū) SELECT @@session.time_zone; # 設(shè)置當(dāng)前會(huì)話時(shí)區(qū) SET time_zone = 'Europe/Helsinki'; SET time_zone = "+00:00"; # 數(shù)據(jù)庫全局時(shí)區(qū)設(shè)置 SELECT @@global.time_zone; # 設(shè)置全局時(shí)區(qū) SET GLOBAL time_zone = '+8:00'; SET GLOBAL time_zone = 'Europe/Helsinki';5.3 DateTime 類型耗費(fèi)空間更大
Timestamp 只需要使用 4 個(gè)字節(jié)的存儲(chǔ)空間,但是 DateTime 需要耗費(fèi) 8 個(gè)字節(jié)的存儲(chǔ)空間。但是,這樣同樣造成了一個(gè)問題,Timestamp 表示的時(shí)間范圍更小。
- DateTime :1000-01-01 00:00:00 ~ 9999-12-31 23:59:59
- Timestamp: 1970-01-01 00:00:01 ~ 2037-12-31 23:59:59
Timestamp 在不同版本的 MySQL 中有細(xì)微差別。
5.4 數(shù)值型時(shí)間戳是更好的選擇嗎?
很多時(shí)候,我們也會(huì)使用 int 或者 bigint 類型的數(shù)值也就是時(shí)間戳來表示時(shí)間。
這種存儲(chǔ)方式的具有 Timestamp 類型的所具有一些優(yōu)點(diǎn),并且使用它的進(jìn)行日期排序以及對(duì)比等操作的效率會(huì)更高,跨系統(tǒng)也很方便,畢竟只是存放的數(shù)值。缺點(diǎn)也很明顯,就是數(shù)據(jù)的可讀性太差了,你無法直觀的看到具體時(shí)間。
數(shù)據(jù)庫中實(shí)際操作:
mysql> select UNIX_TIMESTAMP('2020-01-11 09:53:32'); +---------------------------------------+ | UNIX_TIMESTAMP('2020-01-11 09:53:32') | +---------------------------------------+ | 1578707612 | +---------------------------------------+ 1 row in set (0.00 sec)mysql> select FROM_UNIXTIME(1578707612); +---------------------------+ | FROM_UNIXTIME(1578707612) | +---------------------------+ | 2020-01-11 09:53:32 | +---------------------------+ 1 row in set (0.01 sec)5.5 總結(jié)
每種方式都有各自的優(yōu)勢(shì),根據(jù)實(shí)際場(chǎng)景才是王道。下面再對(duì)這三種方式做一個(gè)簡(jiǎn)單的對(duì)比,以供大家實(shí)際開發(fā)中選擇正確的存放時(shí)間的數(shù)據(jù)類型。
總結(jié)
以上是生活随笔為你收集整理的MySQL面试 (一) 数据类型的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: html原生标签,原生html详情标签(
- 下一篇: xshell 隧道 mysql_u盟及x