MySQL学习 - 数据类型的选择

1. 类似的,数据类型间的,比较


1.1 原则上咱们但愿你这样去选择数据类型

  • 够用的状况下,越小越好
  • 使用简单的数据类型:       理论上MySQL内建类型处理起来更加方便,int会比varchar好处理
  • 尽可能避免使用NULL:          NULL的使用使得MySQL的优化比较难以执行下去
  • 在你设计一张表的时候:   你最好先肯定大的类型例如int, 而后再去肯定小类型如int8


1.2 整数类型

  • TINYINT / SMALLINT / ... / BIGINT 消耗的存储空间逐渐变大
  • 在它们前面加上 UNSIGNED 标志能进一步将存储能力加大一倍
  • 涉及整数计算 最好使用 64 位的 BIGINT
  • INT(11) 这种写法大部分状况下都没什么意义
    • INT(11) 存储能力 = INT(1) 
    • INT(11) 计算能力 = INT(1)
    • 在Mysql一些客户端中,有时候INT(11)会只显示11字符


1.3 实数类型

  • FLOAT[4] / DOUBLE[8] / DECIMAL(a,b) [ max(a,b) + 2 ] 
    • FLOAT / DOUBLE 是常见的单双精度数据,计算过程由CPU本身实现
    • DECIMAL类型的出现是为了存更加精确的小数。 假设你精确到了必定程度,那么CPU自己是没有实现这种东西的计算过程的。 
      • 所以在MYSQL-5.0之前其实是由浮点数模拟的DECIMAL计算
        故而可能会损失一些精度
      • 5之后的版本MYSQL本身实现了DECIMAL计算
        可是就快而言,天然是CPU自身实现计算会更快
  • MYSQL自己存在一种机制,即便你自身指定了精度,可是实际存储的过程当中仍是会作出一些取舍,能够说是本身在悄悄优化,因此建议只指定类型,不要指定精度


1.4 字符串类型

  • VARCHAR(变长) - 存储的时候仅消耗一些必要的空间,可是会额外消耗1~2字节记录长度
    • 最好不要老是更新VARCHAR
      • 假设变长了,可能致使内存页内没有更多空间存储
      • 假设变短了,可能出现一个没法被利用的内存碎片
    • 字符串长度波动幅度很是大的时候用,能占到便宜
  • CHAR(定长)
    • MD5这样的定长度值
    • 由于长度不会变,所以内存利用效率更高
  • VARCHAR & CHAR 具体是如何存储的这要看存储引擎怎么决定
  • 一些行为诸如TRIM是由MYSQL数据库决定的
  • 若是真的按照你说的,VARCHAR只作必要的开销,那么VARCHAR(5) == VARCHAR(200)吗


1.5 枚举ENUM类型

  • 假设如今有三种字符串A/B/C,在使用ENUM的状况下实际存储的时候会变成1/2/3。在对这一列进行排序的时候,也是按照1/2/3的方式进行排序的。
  • 很差的地方:  
    • 排序的时候须要使用FILED( )来指定排序,不然就会按照1/2/3排序
    • 由于ENUM的candidate是固定的,所以但凡想要作出一些修改,最大的可能就是ALTER TABLE
    • 由于实际存储的时候是按照1/2/3存储的,所以转换存在一些开销,好在大部分时候这个映射表并不大,所以开销也不是很大
  • 好的地方:
    • 假设某个属性成为了主键的一部分,面临一些作联表的可能,在联表的时候,作过ENUM映射的表,联的时候会比单纯的字符串快不少
    • 在使用 SHOW TABLE STATUS 展现表当前状态的时候使用ENUM会比使用字符串 data_length 更低


1.6 日期时间类型

  • DATETIME: 日期+时间
  • TIMESTAMP: UNIX时间,开销更小
    • 与时区相关,好比TS=0在美国就会比在英国晚5小时


1.7 标识符 / 索引

  • 标识符有点像一个键,能够用来惟一的肯定一列
  • 最好的选择是使用整数类型做为标识符。 与之相对的是避免使用字符串做为标识符,由于它们会很消耗空间,大部分时候也挺慢
  • 避免使用UUID - MD5 - SHA1等随机字符串做为索引,这些值会随意分布在很大空间内,从而致使INSERT SELECT 变慢
    • 所谓的 "随意分布" / "很大空间" 是指咱们在索引生成之后,SHA1随机生成的新值颇有可能会插入其中,变慢。 带来的其余影响则包含:  页的中间插入 -> 页分裂 / 磁盘随机写入行为
    • 彻底随机字符串会致使 -> 内容写入到内存块彻底随机的地方上,逻辑上相邻的行事实上相距很是远,从而致使SELECT变慢
    • 内存访问上有一种说法叫 "局部性原理", 内存里老是有一小片很"热",老是被访问,这种时候咱们选择缓存这一小片,下次访问缓存就颇有可能直接拿到想要的数据,总体是快的不行。   如今随机数来了,全部地方都是同样"热",我缓存哪儿?我缓存哪儿对我都没有明显的好处


2. 设计一张表你最好这样 :

(接下来可能会反复补充设计表的一些东西)html

2.1 设计表的时候尽可能避免这些

  • 包含有太多列
  • 枚举映射表太长
  • 过多使用NULL, 尽可能避免使用null
    • 你可使用一些符号代替 -1,0 均可以
    • 可是使用NULL也表明必定是坏事,若是你的表里有太多不可能发生的数字自己也很差

2.2 范式 & 反范式

  • 使用范式
    • 好处: 
      • 若是没有范式这种东西,表内有太多冗余的信息,你不能说他们是错误信息,只是太多余,然而在你尝试更新一个字段的时候,哪怕你忘记更新其中一处,这些冗余信息就会变成错误信息
      • 使用范式的状况下更新属性一般更清爽也更快
      • 范式化的表一般更小,所以能直接把整表塞进内存,查询很快
    • 缺点: 
      • 查询全量信息的时候,面临联表,噩梦
  • 使用反范式
    • 好处: 无需关联,快
  • 总结
    • 实际上纯范式化的数据库 & 纯反范式化的数据库都只是理论上的说说,生产环境下我认为应该仍是酌情,以及结合数据库测试的表现来讲
      • 例如你如今有user + message 表, 其中有个字段叫作 account_name_chinese,按照范式这个字段只应该在user表里出现,可是message也会常常须要它,你能够在数据库的测试中的表现下,酌情使用
      • 可是像如今针对 这个字段的更新,你须要更新两张表,这也是你须要考量的点,你会不会常常更新它? 你能接受一次更新两张表吗? 
      • 避免这种问题,使用trigger解决这种麻烦事 ( 什么是 trigger )

2.3 该不应用视图

  • 什么是视图:  
  • 什么是物化视图: 预先计算好的表,会根据一些手段更新
相关文章
相关标签/搜索