转载自  设计数据库表时,你真的会选数据类型吗

关系型数据库,是开发人员最常接触的持久化存储之一了,使用关系型数据库有很多好处,比如支持通过事务处理保持数据的一致性、数据更新的开销很小、可以进行Join等复杂查询等。

同时,还有个好处就是关系型数据库有比较完善的数据类型,支持很多不同类型的数据存储。但是这些数据类型的使用和选择也有很多套路在的,本文就来简单介绍一下。

1. 整数类型

整数类型有:tinyint、smallint、mediumint、int、bigint,分别使用 8、16、24、32、64 位存储空间。

它们可以存储的值范围从 -2 的 (n-1) 次方到 2 的 (n-1) 次方 -1,n 是存储空间的位数。

整数有可选的 unsigned 属性(无符号类型),表示不允许有负值,因此可以使正数上限提高一倍。

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

2.  实数类型

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

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

其中 DECIMAL 也可以用来指定精度,并且它比 FLOAT 和 DOUBLE 更适合做精确计算。在本文就不做详细介绍了,如果有人想了解的话可以给我留言,我下次再写。

3. 字符串类型

字符串类型有:

  1. VARCHAR

  2. CHAR

  3. BLOB

  4. 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 还要多一个字节来记录长度,本来打算节约存储的现在反而得不偿失)

  • 定长的字符串(如 MD5、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 点设计原则:

  1. 更小的通常更好

  2. 简单就好

  3. 尽量避免 NULL

下面对其详细说明一下:

  1. 一般情况下,应该选择可以正确存储数据的最小数据类型,因为它们占用更少的磁盘、内存和 CPU 缓存,并且处理时需要的 CPU 周期也更少。

  2. 简单数据类型的操作需要更少的 CPU 周期。例如,整型比字符操作代价更低,因为字符集和校对规则(排序规则)使字符比较比整型比较更复杂。

  3. 通常情况下,最好指定列为 NOT NULL,除非真的需要存储 NULL 值。因为可为 NULL 的列会使索引、索引统计和值比较都更复杂。可为 NULL 的列会使用更多的存储空间,在 MySQL 里也需要特殊处理。

  4. 当可为 NULL 的列被索引时,每个索引需要一个额外的字节,在 MyISAM 里甚至还可能导致固定大小的索引变成可变大小的索引。通常把可为 NULL 的列改为 NOT NULL 带来的性能比较小,所以在优化时没有必要先在现有表里修改这种情况。

参考:

  • 《高性能 MySQL》

设计数据库表时,你真的会选数据类型吗相关推荐

  1. 设计数据库表时数据类型的选择

    设计数据库表时数据类型的选择 1. 整数类型 整数类型有:tinyint.smallint.mediumint.int.bigint,分别使用 8.16.24.32.64 位存储空间. 它们可以存储的 ...

  2. powerdesign java,PowerDesigner设计数据库表

    1.说明 使用PowerDesigner设计数据库表, 然后将表设计导出为Word文档, 以及MySQL数据库对应的DDL刷库脚本. 2.创建模型 首先创建概念数据模型: File -> New ...

  3. 干掉 powerdesigner,设计数据库表用它就够了

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 点击" 程序员内点事 "关注,选择&q ...

  4. 一篇文章告诉你如何设计数据库表

    0.三大范式及反范式 ◆ 第一范式(1NF):强调的是列的原子性,即列不能够再分成其他几列.  ◆ 第二范式(2NF):首先是 1NF,另外包含两部分内容,一是表必须有一个主键:二是没有包含在主键中的 ...

  5. 根据E-R图设计数据库表

    上图是一个E-R图,一共有三个实体:司机.车辆.车队.并且这几个实体之间互相具有一定的联系. 我们首先把所有实体的表写出来. 数据类型的选择请参考文章:https://blog.csdn.net/qq ...

  6. 数据库建表时,对于字段的数据类型的选择

    本文是<数据库设计那些事>的笔记和思考. 有如下几种情形: 当字段可选择多个类型时(比如生日字段,可以用时间戳,即整数类型,可以用字符串 类型,也可以用日期 类型):整数.二进制 优于 日 ...

  7. Access把每一天的数据累加_如何设计 QQ、微信等第三方账号登陆 ?以及设计数据库表!...

    来源:http://suo.im/5SBVka 多账户的统一登录 名称解释 这里的多账户区别于系统级别的,我们讲的多账户系统是指,在我们互联网应用当中,我们的应用会使用多个第三方账号进行登录,比如现在 ...

  8. oracle数据库纵表设计,oracle 数据库设计-数据库表设计

    在数据库设计中,我的工作中经常会分析怎样商业逻辑中的表格如何设计.再设计表的关系之前 需要先了解关系型数据库特点 1关系型数据库,是指采用了关系模型来组织数据的数据库: 2.关系型数据库的最大特点就是 ...

  9. token 微信access 过期_如何设计 QQ、微信等第三方账号登陆 ?以及设计数据库表!...

    来源:http://suo.im/5SBVka 多账户的统一登录 名称解释 这里的多账户区别于系统级别的,我们讲的多账户系统是指,在我们互联网应用当中,我们的应用会使用多个第三方账号进行登录,比如现在 ...

最新文章

  1. 通过AI翻译大脑信息
  2. [iOS翻译]《The Swift Programming Language》系列:Welcome to Swift-01
  3. ffplay.c学习-4-⾳频输出和⾳频重采样
  4. sql 动态写入数据库字段_批处理写入,动态SQL和参数化SQL,数据库的性能如何?...
  5. eclipse IDE中無法打開android模擬器
  6. Android将应用调试log信息保存在SD卡
  7. java 获取泛型_聊聊Java泛型擦除那些事
  8. RDD和DataFrame和DataSet三者间的区别
  9. 【鱼眼镜头1】鱼眼镜头的四种投影模型(指导镜头的设计),中央镜头综述
  10. mac音频剪辑合并软件哪款比较好用,求推荐
  11. 普元EOS:执行自定义命名sql查询(无参,有参)
  12. 基于卷积神经网络CNN的面部表情识别
  13. 文本框内容改变的绑定事件
  14. 动环监控安装及调试过程,动环监控调试是什么
  15. wordpress实现全站HTTPS
  16. [和管子对话] 1 2007-4-5/对面向对象的你言我语
  17. 一次github和jenkins集成构建异常处理
  18. python代码覆盖率工具——coverage
  19. Sklearn到底是什么?
  20. python解析xml数据_用Python解析XML数据

热门文章

  1. 算法题目——子序列和问题(poj-3061)(尺取法)
  2. java pc计数器_java虚拟机-程序计数器PC Register
  3. Spring5 jar包下载
  4. C++vector容器-互换容器
  5. Circle and Points POJ - 1981(单位圆覆盖最多点)
  6. 单向链表的逆转(数据结构)(c语言)
  7. ./include/caffe/util/cudnn.hpp: error: too few arguments to function ‘SetPooling2dDescriptor
  8. 小 Q 与函数求和 1(牛客练习赛 81 E)
  9. (CCPC 2020 网络选拔赛)HDU 6900 Residual Polynomial(分治 + NTT)
  10. P6154 游走 概率dp