你应该知道的数据库数据类型及其设计原则

1. 整数类型

整数类型有:tinyint、smallint、mediumint、int、bigint,分别使用 八、1六、2四、3二、64 位存储空间。它们能够存储的值范围从 -2 的 (n-1) 次方到 2 的 (n-1) 次方 -1,n 是存储空间的位数。缓存

整数有可选的 unsigned 属性(无符号类型),表示不容许有负值,所以可使正数上限提升一倍。微信

有符号和无符号类型使用相同的存储空间,并具备相同的性能,所以能够根据实际状况选择合适的类型。性能

2. 实数类型

实数类型有:FLOAT、DOUBLE ,分别占用 4,8 字节。优化

若是插入值的精度(即:数字总位数)高于实际定义的精度,系统会自动进行四舍五入处理,使值的精度达到要求。ui

其中 DECIMAL 也能够用来指定精度,而且它比 FLOAT 和 DOUBLE 更适合作精确计算。在本文就不作详细介绍了,若是有人想了解的话能够给我留言,我下次再写。spa

3. 字符串类型

字符串类型有:设计

  • VARCHAR
  • CHAR
  • BLOB
  • TEXT

因为 BLOB 和 TEXT 不经常使用且因为篇幅问题,就不展开描述了。本文主要对 VARCHAR 和 CHAR 进行介绍,它们的区别以下表:排序

对比内容 VARCHAR CHAR
是否固定长度
存储上限字节 65535 255
保存或检索值时,是否删除字符串末尾空格
超过设置的范围后,字符串是否会被截断

除了以上不一样以外,VARCHAR 还须要额外使用 1 个或 2 个字节来记录字符串长度。若是列的最大长度小于或等于 255 字节,则使用 1 个字节,不然使用 2 个字节。索引

因为 VARCHAR 是变长的,因此在 update 时,可能使行变得比原来更长,这就致使须要进行额外的工做。若是一个行占用的空间增长,而且在页内没有更多空间能够存储,在这种状况下,不一样存储引擎的处理方式不同的。例如:MyISAM 会将行拆分为不一样的片断存储,InnoDB 则须要分裂页来使行能够放进页内。图片

在选择使用场景上,重点要抓住 VARCHAR 是变长,CHAR 是定长的特色。

好比在这些状况更适合使用 VARCHAR:

  • 字符串的最大长度比平均长度大不少;
  • 字段更新次数少(因此碎片不是问题);
  • 使用了像 UTF-8 这样复杂的字符集,每一个字符都使用不一样的字节数进行存储。

而在这些状况则更适合使用 CHAR:

  • 存储很短的字符串(而 VARCHAR 还要多一个字节来记录长度,原本打算节约存储的如今反而得不偿失)
  • 定长的字符串(如 MD五、uuid);
  • 须要频繁修改的字段。由于 VARCHAR 每次存储都要有额外的计算,获得长度等工做;

这里抛出一个小问题:使用 VARCHAR(5) 和 VARCHAR(200) 来存储 ‘hello’ 的空间开销是同样的。那么使用更短的列有什么好处呢?(思考几秒钟?)

答案:节约内存,由于更长的列会消耗更多的内存。MySQL 一般会分配固定大小的内存块来保存内部值。尤为是使用内存临时表进行排序或操做时会特别糟糕。在利用磁盘临时进行排序时也一样糟糕。

因此最好的策略是只分配真正须要的空间。

4. 日期和时间类型

下面表格是 TIMESTAMP 和 DATETIME 的一些对比:

对比内容 TIMESTAMP DATETIME
占用字节 4 8
时间范围 1970-01-01 08:00:01 ~ 2038-01-19 11:14:07 1000-01-01 00:00:00 ~ 9999-12-31 23:59:59
存储的数据是否随时区变化

若是在插入数据时,没有指定第一个 TIMESTAMP 列的值,MySQL 则将这个列设置为当前时间,同时 TIMESTAMP 比 DATETIME 的空间效率更高。

最后,网上有不少讨论,时间到底要使用 INT、TIMESTAMP、DATETIME 哪一种类型更适合。我认为这没有一个固定答案,具体能够参考文章:《选择合适的 MySQL 日期时间类型来存储你的时间》,我放在原文连接里面了。

5. 设计合理的数据类型

提供给你们 3 点设计原则:

  • 更小的一般更好
  • 简单就好
  • 尽可能避免 NULL

下面对其详细说明一下:

  1. 通常状况下,应该选择能够正确存储数据的最小数据类型,由于它们占用更少的磁盘、内存和 CPU 缓存,而且处理时须要的 CPU 周期也更少。
  1. 简单数据类型的操做须要更少的 CPU 周期。例如,整型比字符操做代价更低,由于字符集和校对规则(排序规则)使字符比较比整型比较更复杂。
  1. 一般状况下,最好指定列为 NOT NULL,除非真的须要存储 NULL 值。由于可为 NULL 的列会使索引、索引统计和值比较都更复杂。可为 NULL 的列会使用更多的存储空间,在 MySQL 里也须要特殊处理。
  1. 当可为 NULL 的列被索引时,每一个索引须要一个额外的字节,在 MyISAM 里甚至还可能致使固定大小的索引变成可变大小的索引。一般把可为 NULL 的列改成 NOT NULL 带来的性能比较小,因此在优化时没有必要先在现有表里修改这种状况。

参考:
《高性能 MySQL》

欢迎关注微信公众号「不仅Java」,后台回复「电子书」,送说不定有你想要的呢
图片描述

相关文章
相关标签/搜索