
提到 IP 地址(IPv4),大夥兒腦子裡肯定馬上能浮現類似於
192.168.0.1
、127.0.0.1
這種常見的 IP 地址,然後結合這個問題 “MySQL 中用什麼資料型別存 IP 地址?”,於是乎脫口而出用 char
字串型別存。面試官一臉冷漠,你頓時意識到情況不對,又仔細琢磨了一下。

然後發現,這個 IP 地址的長度是變化的,最短可以是
0.0.0.0
只需要 7 位,最長可以是 255.255.255.255
需要 15 位,於是自信地回答使用 varchar(15)
來儲存 IP 地址,併為自己能夠想到這一層而暗自竊喜。誰知面試官竟輕蔑一笑,問你 “確定嗎?”,你覺得這是面試官在考驗你,於是堅定的回答 “確定”。
然後就開始了下一題
……
人們經常使用
varchar(15)
列來儲存 IP 地址,但事實上這並不是最優解。IP 地址的本質是 32 位無符號整數,類似於
192.168.0.1
這種點分十進位制的字串寫法只是為了幫助人們理解和記憶,192.168.0.1
對應的十進位制表示是 無符號整數 3232235521
。所以,說用字串型別存 IP 地址的,其實是潛意識中以為 IP 地址是字串,存的是點分十進位制的字串,但正確的應該是存 32 位的無符號整數
所謂有符號數其實就是將最高位作為符號位,比如 32 位的有符號 INT,最高位是符號位,剩下 31 位才是真實的數值,所以有符號 INT 的取值區間為:
無符號 INT 的取值區間為:
下表列出了 MySQL 出各個整數型別有符號和無符號的的取值範圍,在定義表時,可以在資料型別後面新增關鍵字
UNSIGNED
來定義無符號整數,否則預設為有符號整數:型別 | 有符號數取值範圍 | 無符號數取值範圍 |
---|---|---|
TINYINT(1 位元組,8 bit) | -128 〜 127 | 0 〜 255 |
SMALLINT(2 位元組,16 bit) | -32768 〜 32767 | 0 〜 65535 |
MEDIUMINT(3 位元組,24 bit) | -8388608 〜 8388607 | 0 〜 16777215 |
INT(4 位元組,32 bit) | -2147483648 〜 2147483647 | 0 〜 4294967295 |
BIGINT(8 位元組,64 bit) | -9223372036854775808 〜 9223372036854775807 | 0 〜 18446744073709551615 |
結合上表,可以看出,32 位的無符號
INT
正好可以容納 IPv4 地址,下面是 INT UNSIGNED
和 VARCHAR(15)
兩種資料型別的對比:-
儲存空間:4 位元組的 INT
型別 15 位元組的VARCHAR(15)
更加節省儲存空間。另外,VARCHAR 除了會儲存需要的字元數,還會另加一個位元組來記錄長度(如果列宣告的長度超過 255,則使用兩個位元組記錄長度),所以VARCHAR(15)
其實要佔用 16 個位元組。 -
檢索速度:如果我們要在 IP 地址上建立索引,那麼對於字串索引來說,整數索引的檢索速度簡直就是降緯打擊了,因為字串型別的比較是需要從第一位字元開始遍歷依次進行的,速度較慢。
MySQL 非常貼心地提供了 IPv4 地址點分十進位制和無符號整數的相互轉換函式,
inet_aton
和 inet_ntoa
(底層是二進位制移位操作,速度很快):
當然你更應該在業務中去執行這些轉換,減輕 MySQL 的壓力。
歡迎加入我的知識星球,全面提升技術能力。
👉 加入方式,“長按”或“掃描”下方二維碼噢:

星球的內容包括:專案實戰、面試招聘、原始碼解析、學習路線。





文章有幫助的話,在看,轉發吧。
謝謝支援喲 (*^__^*)
關鍵詞
位元組
索引
長度
地址
0.0