【MySQL】varbinary 真的比varchar 更合適?
一 前言
在討論資料表欄位設計的時候,有同學提出使用vabinary 代替 varchar ,部分開發不明所以,其實我也是。兩者之間具體有什麼區別?使用vabinary 代替 varchar 對業務有何優勢?本文嘗試從效能,資料大小,查詢,建立索引等對比功能等方面進行研究,有不妥或者不到位之處還請各位讀者朋友提示。
二 對比測試
2.1 測試環境
資料庫版本 Percona Server 5.6.24-72.2-log
2.2 定義
varchar(N) 字串型別,用於儲存變長字串,使用表預設或者指定的校驗集合,其中N代表儲存字元的個數,詳細資訊請移步《淺談varchar(N)》.
varbinary(N)二進位制字串型別,以二進位制位元組串儲存字元,無字符集校驗區別,均以二進位制實際數值作比較。
2.3 長度定義
varchar儲存的是字元個數,varbinary儲存的是位元組個數。
分析:
varbinary(N)中長度N指的是位元組串的長度,一個數字/英文字母佔用1個位元組,一個漢字佔用3個位元組(預設utf8、utf8mb4字符集),指定N 則可以儲存 N 個數字或者字母,N/3個漢字。
varchar(N)中長度N指的是字串的長度,一個數字/英文字母/漢字佔用一個字元,指定N 可以儲存N個字元。
注意兩種儲存型別支援的欄位長度計算方式的不同,會給開發帶來一定的困擾,使用varbinary的開發需要深入瞭解該欄位的儲存單位,設計欄位的時候還要根據業務邏輯計算好N的值是多少。否則可能會被截斷 ,在sql_mode為嚴格模式時則會報錯。
2.4 索引功能
分別對name欄位建立索引
分析:
基於 varbinary和 varchar 儲存字元的長度定義不同,varchar 可以儲存字串前191個字元的索引,varbinary 欄位的索引則最多可以儲存767位元組。如果是英文字母則可以儲存更長的字串。
2.5 校驗方面
分析:
varbinary儲存的是二進位制位元組串而不是字串,這意味著它沒有字符集校驗的概念,排序和比較都是基於位元組中的實際數值大小進行的。varchar型別儲存的列在比較的時候是透過字符集的方式進行的,varchar 中'ABAA'和'abaa'是一致的.
2.6 效能測試
使用mysqlslap 進行10個併發100w次查詢做對比
分析
簡單的select查詢對比來看
varbinary 30.569s
varchar 31.986s
varbinary 相對效能有 1.4s 約4%的效能提升,在壓測環境下每秒幾乎3wqps,如果是普通的業務場景1000-2000左右的qps,varbinary帶來的效能可以忽略不計.
三 總結
本文從儲存長度單位,索引,查詢條件校驗,效能方面做了測試,其優點是 無需考慮字符集,比較的時候安裝位元組比較理論上比字元要快(測試結果的確會快4% 左右,但不明顯),考慮實際應用的時候 varbinary 儲存單位的改變給開發帶來更多的迷惑性,尤其是使用 varbinary 儲存漢字時,開發需要更多的考慮具體設計多長才能滿足業務需求,存在被截斷的風險。從結果上來看並沒有特別好的理由讓我們選擇varbinary。
推薦文章《官方文件》
在討論資料表欄位設計的時候,有同學提出使用vabinary 代替 varchar ,部分開發不明所以,其實我也是。兩者之間具體有什麼區別?使用vabinary 代替 varchar 對業務有何優勢?本文嘗試從效能,資料大小,查詢,建立索引等對比功能等方面進行研究,有不妥或者不到位之處還請各位讀者朋友提示。
二 對比測試
2.1 測試環境
資料庫版本 Percona Server 5.6.24-72.2-log
-
create table vbinary
-
(
-
id int primary key auto_increment ,
-
val varbinary(776) not null default ''
-
) engine=innodb default charset=utf8mb4;
-
-
create table vachar
-
(
-
id int primary key auto_increment ,
-
val varchar(12) not null default ''
-
) engine=innodb default charset=utf8mb4;
-
insert into vbinary(val) values('abaa'),('aabb'),('bcdd'),('ccdd');
- insert into vachar(val) values('abaa'),('aabb'),('bcdd'),('ccdd')
varchar(N) 字串型別,用於儲存變長字串,使用表預設或者指定的校驗集合,其中N代表儲存字元的個數,詳細資訊請移步《淺談varchar(N)》.
varbinary(N)二進位制字串型別,以二進位制位元組串儲存字元,無字符集校驗區別,均以二進位制實際數值作比較。
2.3 長度定義
varchar儲存的是字元個數,varbinary儲存的是位元組個數。
-
test [RW] 10:57:50 >insert into vbinary (val,name) value('2msdmlsdyo2enwlenw','disodmalsdsi');
-
Query OK, 1 row affected, 1 warning (0.00 sec)
-
test [RW] 10:57:55 >show warnings;
-
+---------+------+------------------------------------------+
-
| Level | Code | Message |
-
+---------+------+------------------------------------------+
-
| Warning | 1265 | Data truncated for column 'val' at row 1 |
-
+---------+------+------------------------------------------+
-
1 row in set (0.00 sec)
-
test [RW] 10:58:11 >insert into vbinary (val,name) value('有贊是一家移動零售服務提供商','disodmalsdsi');
-
Query OK, 1 row affected, 1 warning (0.01 sec)
-
test [RW] 10:59:00 >show warnings;
-
+---------+------+------------------------------------------+
-
| Level | Code | Message |
-
+---------+------+------------------------------------------+
-
| Warning | 1265 | Data truncated for column 'val' at row 1 |
-
+---------+------+------------------------------------------+
-
1 row in set (0.00 sec)
-
test [RW] 10:59:08 >select * from vbinary;
-
+----+--------------+--------------+
-
| id | val | name |
-
+----+--------------+--------------+
-
| 6 | 2msdmlsdyo2e | disodmalsdsi |
-
| 7 | 有贊是一 | disodmalsdsi | #
-
+----+--------------+--------------+
-
7 rows in set (0.00 sec)
-
test [RW] 10:59:12 >insert into vachar(val,name) value('有贊是一家移動零售服務提供商','disodmalsdsi');
-
Query OK, 1 row affected, 1 warning (0.00 sec)
-
test [RW] 11:00:02 >show warnings;
-
+---------+------+------------------------------------------+
-
| Level | Code | Message |
-
+---------+------+------------------------------------------+
-
| Warning | 1265 | Data truncated for column 'val' at row 1 |
-
+---------+------+------------------------------------------+
- 1 row in set (0.00 sec)
-
test [RW] 11:00:06 >select * from vachar;
-
+----+--------------------------------------+--------------+
-
| id | val | name |
-
+----+--------------------------------------+--------------+
-
| 4 | ccdd | yz |
-
| 5 | 有贊是一家移動零售服務提 | disodmalsdsi |
-
+----+--------------------------------------+--------------+
- 5 rows in set (0.00 sec)
varbinary(N)中長度N指的是位元組串的長度,一個數字/英文字母佔用1個位元組,一個漢字佔用3個位元組(預設utf8、utf8mb4字符集),指定N 則可以儲存 N 個數字或者字母,N/3個漢字。
varchar(N)中長度N指的是字串的長度,一個數字/英文字母/漢字佔用一個字元,指定N 可以儲存N個字元。
注意兩種儲存型別支援的欄位長度計算方式的不同,會給開發帶來一定的困擾,使用varbinary的開發需要深入瞭解該欄位的儲存單位,設計欄位的時候還要根據業務邏輯計算好N的值是多少。否則可能會被截斷 ,在sql_mode為嚴格模式時則會報錯。
2.4 索引功能
分別對name欄位建立索引
-
test [RW] 10:47:01 >alter table vbinary add name varbinary(255) not null default 'yz';
-
Query OK, 0 rows affected (0.02 sec)
-
Records: 0 Duplicates: 0 Warnings: 0
-
test [RW] 10:47:24 >alter table vbinary add key idx_name(name);
-
Query OK, 0 rows affected (0.01 sec)
-
Records: 0 Duplicates: 0 Warnings: 0
-
test [RW] 10:48:25 >rename table vchar to vachar;
-
Query OK, 0 rows affected (0.01 sec)
-
test [RW] 10:49:00 >alter table vachar add name varchar(255) not null default 'yz';
-
Query OK, 0 rows affected (0.02 sec)
-
Records: 0 Duplicates: 0 Warnings: 0
-
test [RW] 10:49:31 >alter table vachar add key idx_name(name);
-
Query OK, 0 rows affected, 1 warning (0.02 sec)
-
Records: 0 Duplicates: 0 Warnings: 1
-
test [RW] 10:49:53 >show Warnings;
-
+---------+------+---------------------------------------------------------+
-
| Level | Code | Message |
-
+---------+------+---------------------------------------------------------+
-
| Warning | 1071 | Specified key was too long; max key length is 767 bytes |
-
+---------+------+---------------------------------------------------------+
-
1 row in set (0.00 sec)
-
test [RW] 10:50:06 >show create table vachar \G
-
*************************** 1. row ***************************
-
Table: vachar
-
Create Table: CREATE TABLE `vachar` (
-
`id` int(11) NOT NULL AUTO_INCREMENT,
-
`val` varchar(12) NOT NULL DEFAULT '',
-
`name` varchar(255) NOT NULL DEFAULT 'yz',
-
PRIMARY KEY (`id`),
-
KEY `idx_name` (`name`(191))
-
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4
- 1 row in set (0.00 sec)
-
test [RW] 10:50:19 >show create table vbinary \G
-
*************************** 1. row ***************************
-
Table: vbinary
-
Create Table: CREATE TABLE `vbinary` (
-
`id` int(11) NOT NULL AUTO_INCREMENT,
-
`val` varbinary(12) NOT NULL DEFAULT '',
-
`name` varbinary(255) NOT NULL DEFAULT 'yz',
-
PRIMARY KEY (`id`),
-
KEY `idx_name` (`name`)
-
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4
- 1 row in set (0.00 sec)
-
test [RW] 11:53:08 >create table vbinary1
-
-> (
-
-> id int primary key auto_increment ,
-
-> val varbinary(776) not null default ''
-
-> ) engine=innodb default charset=utf8mb4;
-
Query OK, 0 rows affected (0.01 sec)
-
test [RW] 11:53:09 >alter table vbinary1 add key idx_val(val);
-
Query OK, 0 rows affected, 1 warning (0.02 sec)
-
Records: 0 Duplicates: 0 Warnings: 1
-
test [RW] 11:53:37 >show Warnings;
-
+---------+------+---------------------------------------------------------+
-
| Level | Code | Message |
-
+---------+------+---------------------------------------------------------+
-
| Warning | 1071 | Specified key was too long; max key length is 767 bytes |
-
+---------+------+---------------------------------------------------------+
-
1 row in set (0.00 sec)
-
test [RW] 11:53:44 >show create table vbinary1 \G
-
*************************** 1. row ***************************
-
Table: vbinary1
-
Create Table: CREATE TABLE `vbinary1` (
-
`id` int(11) NOT NULL AUTO_INCREMENT,
-
`val` varbinary(776) NOT NULL DEFAULT '',
-
PRIMARY KEY (`id`),
-
KEY `idx_val` (`val`(767)) ## 被修改為 767 ,索引支援的最大位元組數。
-
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
- 1 row in set (0.00 sec)
基於 varbinary和 varchar 儲存字元的長度定義不同,varchar 可以儲存字串前191個字元的索引,varbinary 欄位的索引則最多可以儲存767位元組。如果是英文字母則可以儲存更長的字串。
2.5 校驗方面
-
test [RW] 12:15:06 >select * from vachar where val='ABAA';
-
+----+------+------+
-
| id | val | name |
-
+----+------+------+
-
| 1 | abaa | yz |
-
+----+------+------+
-
1 row in set (0.00 sec)
-
test [RW] 12:14:31 >select * from vbinary where val='ABAA';
-
Empty set (0.00 sec)
-
test [RW] 12:15:11 >select * from vbinary where val='abaa';
-
+----+------+------+
-
| id | val | name |
-
+----+------+------+
-
| 1 | abaa | yz |
-
+----+------+------+
- 1 row in set (0.00 sec)
varbinary儲存的是二進位制位元組串而不是字串,這意味著它沒有字符集校驗的概念,排序和比較都是基於位元組中的實際數值大小進行的。varchar型別儲存的列在比較的時候是透過字符集的方式進行的,varchar 中'ABAA'和'abaa'是一致的.
2.6 效能測試
使用mysqlslap 進行10個併發100w次查詢做對比
-
[root@rac4 00:31:35 ~]
-
# time mysqlslap --no-defaults -uroot --create-schema=test -S /srv/my3306/run/mysql.sock --number-of-queries=1000000 --concurrency=10 --query="select * from vbinary where val='abaa';"
-
Benchmark
-
Average number of seconds to run all queries: 30.569 seconds
-
Minimum number of seconds to run all queries: 30.569 seconds
-
Maximum number of seconds to run all queries: 30.569 seconds
-
Number of clients running queries: 10
-
Average number of queries per client: 100000
-
real 0m30.574s
-
user 0m8.124s
-
sys 0m6.286s
-
[root@rac4 00:32:18 ~]
-
# time mysqlslap --no-defaults -uroot --create-schema=test -S /srv/my3306/run/mysql.sock --number-of-queries=1000000 --concurrency=10 --query="select * from vachar where val='abaa';"
-
Benchmark
-
Average number of seconds to run all queries: 31.986 seconds
-
Minimum number of seconds to run all queries: 31.986 seconds
-
Maximum number of seconds to run all queries: 31.986 seconds
-
Number of clients running queries: 10
-
Average number of queries per client: 100000
-
real 0m31.991s
-
user 0m8.351s
- sys 0m6.407s
簡單的select查詢對比來看
varbinary 30.569s
varchar 31.986s
varbinary 相對效能有 1.4s 約4%的效能提升,在壓測環境下每秒幾乎3wqps,如果是普通的業務場景1000-2000左右的qps,varbinary帶來的效能可以忽略不計.
三 總結
本文從儲存長度單位,索引,查詢條件校驗,效能方面做了測試,其優點是 無需考慮字符集,比較的時候安裝位元組比較理論上比字元要快(測試結果的確會快4% 左右,但不明顯),考慮實際應用的時候 varbinary 儲存單位的改變給開發帶來更多的迷惑性,尤其是使用 varbinary 儲存漢字時,開發需要更多的考慮具體設計多長才能滿足業務需求,存在被截斷的風險。從結果上來看並沒有特別好的理由讓我們選擇varbinary。
推薦文章《官方文件》
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/22664653/viewspace-2135146/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- mysql的varchar欄位最大長度真的是65535嗎?MySql
- MySQL varchar詳解MySql
- mysql innodb 主鍵INT、BIGINT、VARCHAR併發插入效能對比MySql
- Linux適合自學還是培訓?哪種方法更合適?Linux
- MySQL 中 VARCHAR 最大長度及 CHAR 和 VARCHAR 的區別MySql
- 2 - 到底哪種數倉設計模型更合適模型
- MySQL中CHAR和VARCHAR區別MySql
- [譯] JavaScript 是如何工作的:對比 WebAssembly + 為什麼在某些場景下它比 JavaScript 更合適JavaScriptWeb
- 初學程式設計,Scratch和Python哪個更合適?程式設計Python
- binary和varbinary的區別
- 例項操作mysql varchar型別求和MySql型別
- 初學Linux哪個發行版本好?這些更合適!Linux
- MySQL資料型別操作(char與varchar)MySql資料型別
- MySQL動態修改varchar長度的方法MySql
- MySQL中int、char、varchar的效能淺談MySql
- 從事Web開發工作,學python和Java哪個更合適?WebPythonJava
- mysql中varchar型別最大長度測試MySql型別
- 點晴ERP和傳統ERP哪個更合適模切企業
- MySQL單表存多大的資料量比較合適MySql
- 為什麼ElasticSearch比MySQL更適合全文索引ElasticsearchMySql索引
- 5600 XT上市,2000元級遊戲顯示卡市場誰更合適?遊戲
- 對於初學者而言,python和C語言選擇哪個更合適?PythonC語言
- 你真的懂 == 比較嗎
- MySQL VARCHAR型別欄位到底可以定義多長MySql型別
- Mysql真的有缺點嗎?MySql
- ClickHouse 與 MySQL 資料庫適用場景對比總結MySql資料庫
- 關於mysql設定varchar 欄位的預設值''和null的區別,以及varchar和char的區別MySqlNull
- MySQL的varchar儲存原理:InnoDB記錄儲存結構MySql
- 面試官:MySQL 中 varchar(n) 中 n 最大取值為多少?面試MySql
- 胡家奇:警惕人工智慧 比無條件擁抱更合情合理人工智慧
- 部落格資料庫要連線Elasticsearch,使用MySQL還是MongoDB更合理資料庫ElasticsearchMySqlMongoDB
- 學習Python線上和線下培訓有什麼區別?哪種更合適?Python
- 你是否真的適合搞NDK開發?
- long2varchar 把long轉換為varchar2
- 深入char、varchar、text
- Android Pie SDK 與 Kotlin 更合拍AndroidKotlin
- Mysql varchar型別欄位為什麼經常定義為255MySql型別
- 應用系統適配瀚高報錯:欄位為numeric,但是表示式為varchar
- 3D 建模軟體哪家強?沒有最好只有更合適,小白建議學習這3個3D