mysql进阶系列:表设计如何更好的选择数据类型

日常工作中我们会接触到不同业务,同样也会设计不同的表,但是你有真正考虑的mysql支持的那些数据类型吗?知道如何根据不同的需求选择最合适或者正确的类型吗。

存储字符串类型只知道选择varchar , 是否知道字符串还有char, text, blob 。

存储数字类型只知道选择 int,float,double,是否知道还有tinyint,smallint 等。

看完这篇文章相信你在以后的表设计中不会再纠结究竟该使用什么字段了。

优化选择数据类型的简单原则:

1. 更小的通常更好

更小的数据类型占用更少的磁盘,内存和CPU缓存,而且处理时需要的CPU周期也更少,所以会更快(但是要确保没有低估需要存储的值的范围)

2. 简单就好

简单的数据类型的操作通常需要更少的CPU周期。

例如:

  1. 整型比字符串操作代价更低,因为字符集和校对规则使 字符串比较 比 整型比较 更复杂。

  2. 使用mysql自建类型而不是字符串来存储日期和时间

  3. 用int存储IP地址比字符串要节约空间(ip用select INET_ATON('192.1.1.101') 和 select INET_NTOA(131351321))

3. 尽量避免null

如果查询中包含null的列使得索引,索引统计和值比较都更为复杂。所以如果在列上建索引,就应该尽量避免设计成可为null的列。

实际数据类型

1. 整数类型

可以使用的整数类型存储空间(位)由小到大分别是tinyint(8)、smallint(16)、mediumint(24)、int(32)、bigint(64)。

如何选择:尽可能使用满足需求的最小数据类型。

例如: 性别只有男和女可能还有未知,如果用数字表示就是未知(1),男(0),女(2),那么类型可以选择tinyint,没必要选择其他的更大的存储空间的类型。

小知识点1: 整数类型中还有个可选项UNSIGNED属性,表示不允许有负值。这可以使得正整数的上限提高一倍。例如本来tinyint 可以存储的范围是-128~127,而tinyint UNSIGNED 可以存储的范围变成0~255(有无UNSIGNED 存储空间都是一样的,性能也不变)。

小知识点2: mysql中可以设置类型的宽度,例如int(11),实际上是没有意义的,只是用来交互工具显示字符的个数,实际上对于存储和计算来说,int(1)和int(10) 是相同的。

2. 实数类型

实数是带有小数部分的数字,而且不只是为了存储小数部分,也可以使用DECIMAL存储比BIGINT还大的整数。

Decimal 类型用于存储精确的小数。(CPU支持原生浮点计算,不支持对decimal的直接计算,所以浮点运算更快)。

浮点类型在存储同样范围的值时,通常比decimal使用更少的空间,float用4字节存储,double用8个字节(mysql使用double作为内部浮点计算)

只有需要对小数进行精确计算时才使用decimal(例如财务数据),但是当数据量较大的时候,可以考虑使用bigint代替decimal,将需要存储的货币单位根据小数的位数乘以相应的倍数即可

  • 假如要存储财务数据精确到万分之一,可以把所有金额乘以一百万,

    然后将结果存储在bigint里,可以避免浮点存储计算不精确和decimal精确计算代价高的问题。

3. 字符串类型

字符串类型包含varchar(工作中首选),char,text,blob。

varchar:存储的是可变长度字符串,比定长类型更节省空间(越短字符串使用越少的空间)。

  1. 使用最小的符合需求的长度。

  2. varchar(n) n<=255的时候使用一个字节来保存长度,当n>255的时候需要两个字节保存长度。

  3. varchar(5)和varchar(200)保存同样的内容,硬盘的存储空间是一样的,不同的是内存的消耗。mysql通常会分配固定大小的内存块来保存内部值,尤其是使用内存临时表进行排序或者操作的时候会很糟糕。

所以最好是只分配真正需要的空间。

应用场景:

存储波动长度较大的数据,如:文章,有的短有的长。

字符串很少更新的场景,每次更新都会重新算并使用额外存储空间保存长度。

适合保存多字节字符,如汉字,特殊字符等。

char: 定长,最大长度255,

存储char值时,mysql会删除所有数据的末尾空格,

比较适合非常短的数据,例如char(1)来存储Y和N的值。

应用场景:

  1. 存储长度波动不大的数据,如:md5摘要(加密后的密码)

  2. 存储短字符串,经常更新的字符串。

BLOB和TEXT类型

BLOB和text是存储很大的数据而设计的字符串数据类型,分别采用二进制和字符方式存储。

不建议使用,数据量很大的时候会影响效率

4. 日期和时间

dateTime8个字节的存储空间,可以保存大范围的值,保存1000-01-01到9999-12-31之间的日期,精度为秒,将日期和时间封装到格式为YYYYMMDDHHMMSS的整数中,与时区无关。不要使用字符串存储日期类型,占用空间大,损失日期类型函数的便捷性。

timestamp4个字节的存储空间,保存了从1970年1月1日午夜(格林尼治标准时间)以来的秒数,和unix时间戳相同。timestamp的范围只表示从1970年到2038年。timestamp的显示的值依赖于时区。

date3个字节的存储空间,date类型还可以利用日期时间函数进行日期之间的计算。用于保存1000-01-01到9999-12-31之间的日期。

如果想要存储更小粒度的日期和时间值: 可以使用bigint 类型存储微秒级别的时间戳,或者使用double存储秒之后的小数部分

5. 枚举类型

使用枚举替代常用字符串类型,没有生气存储枚举类型会非常紧凑,会根据列表值的数据压缩到一个或者两个字节中,mysql会将每个值在列表中的位置保存为整数,并且在表的.frm文件中保存‘数字’,‘字符串’的映射关系的查找表。

如果直接在数据库存储枚举性别,0代表男,1代表女,查询的时候可以直接看到男/女

mysql> create table enum_test( sex enum('男','女','未知') not null ) charset=utf8;

Query OK, 0 rows affected (0.03 sec)

mysql> INSERT INTO enum_test(sex) values('男'),('女'),('未知'),('男');

Query OK, 4 rows affected (0.01 sec)

Records: 4 Duplicates: 0 Warnings: 0

mysql> select * from enum_test;

+--------+

| sex  |

+--------+

| 男   |

| 女   |

| 未知  |

| 男   |

+--------+

4 rows in set (0.00 sec)

-- 实际底层存储的是整型值
mysql> select sex+0 from enum_test;
+-------+
| sex+0 |
+-------+
|     1 |
|     2 |
|     3 |
|     1 |
+-------+
4 rows in set (0.00 sec)

如果感觉类型的选择没那么重要,是因为遇到的数据体量比较小,但是如果表的数据量很大的话,就会凸显出数据类型的重要性,合适的类型节省的空间和内存就很重要了。

一句话:最好是只分配真正需要的空间。

欢迎关注公众号:纪先生笔记
持续更新mysql进阶系列,还有各种实际问题解决

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,186评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,858评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,620评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,888评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,009评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,149评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,204评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,956评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,385评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,698评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,863评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,544评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,185评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,899评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,141评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,684评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,750评论 2 351

推荐阅读更多精彩内容