🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
**更小的通常更好** 一般情况下,应该尽量使用可以正确存储数据的最小数据类型.更小的数据类型通常更快,因为他们占用更少的磁盘,内存和cpu缓存,并且处理时需要的cpu周期更少 但是要确保没有低估需要存储的值的范围,因为在schema中的多个地方增加数据类型的范围是一个非常耗时和痛苦的操作. 如果无法确定那个数据类型是最好的.要选择你认为不会超过范围的最小类型(如果系统不是很忙或者存储的数据量不多或者是在可以轻易修改设计的早期阶段) **简单就好** 简单的数据类型的操作通常需要更少的cpu周期.例如,整形比字符操作代价更低. 因为字符集和校对规则(排序规则)使字符比较比整形比较更为复杂 这里有两个例子:一个是应该使用mysql内建的类型(date time datatime),而不是字符串来存储日期和时间,另外一个是应该用整形存储IP地址 **尽量避免使用null** 很多表都包含可为null的列,即使应用程序并不需要保持NULL也是如此,这是因为可为NULL是列的默认属性. 通常情况下最好指定列为not null,除非真的需要存储NULL值 如果查询中包含可为null的列,对mysql来说更难优化,因为可为null的列使得索引,索引统计和值比较都更复杂.可为null的列会使用更多的存储空间,在mysql中也要特殊处理 当可为null的列被索引的时候,每一个索引记录需要一个额外的字节,在myisam里甚至还可能导致固定大小的索引(例如只有一个整数列的索引)变成可变大小的索引 通常把可为null的列改为not null带来的性能提升的比较小,所以(调优时)没有必要首先在现有的schema中查找并修改掉这种情况,除非确定这会导致问题. 但是,如果计划在列上建索引,就应该尽量避免设计成可为null的列 Innodb使用单独的位(bit)存储NULL值,所以对于稀疏数据(很多值为null,只有少数行有非null值)有很好的空间效率.但是这不适用于myisam 例如datetime和timesamp列都可以存储相同类型的数据:时间和日期,精确到秒,然而timestamp只使用datetime一半的存储空间,并且会根据时区变化,具有特殊的自动更新能力 另一方面,timestamp允许的时间范围要小的多,有时候它的特殊能力会成为障碍 **慷慨是不明智** 使用`varchar(5)` 和 `varchar(200)` 存储 'hello' 的空间开销是一样的.那么使用更短的列有什么优势吗? 事实证明有很大的优势.更长的列会消耗更多的内存,因为mysql通常会分配固定大小的内存块来保存内部的值 尤其是使用内存临时表进行排序或操作时会特别糟糕.在利用磁盘临时表进行排序时也同样糟糕 所以最好的策略是分配真正需要的空间 **使用枚举(ENUM)代替字符串类型** 有时候可以使用枚举列代替常用的字符串类型. 枚举列可以把一些不重复的字符串存储成一个预定义的集合. mysql在存储枚举时非常紧凑,会根据列表值的数量压缩到一个或者两个字节中 mysql在内部会将每个值在列表中的位置保存为整数,并且在表的.frm文件中保存"数字-字符串"映射关系的'查找表' ![](https://box.kancloud.cn/c6911ff3793124031852bc40e807b8f0_688x619.png) 一种绕过这种限制的方式是按照需要的顺序来定义枚举列, 另外也可以在查询中使 `field()` 函数显式的指定排序顺序,但这会导致mysql无法利用索引消除排序 ![](https://box.kancloud.cn/f39a0c508601d742ec9bf617cce269c0_795x464.png) 我们用varchar和enum列的速度 ![](https://box.kancloud.cn/696489fdd75f3bc9636873e619d926a7_329x151.png) ![](https://box.kancloud.cn/f8b008aa2c873183c853a239f046b14a_829x335.png)