只有选择合适的数据类型, 才能发挥数据库的性能
选择优化的数据类型
原则
-
更小(数据类型占用的空间更小, 也意味着, 可以表示的范围也少)的通常更加好
一般情况下, 应该尽量使用可以正确存储数据的最小的数据类型. 更小的数据类型通常更加快, 因为他们占用的更少的磁盘, 内存, 和 cpu 缓存, 并且处理时需要的 cpu 周期也更少. 需要提前做好数据范围的规划, 确保选取的类型能够存储值的范围
-
简单就好
简单的数据类型的操作通常需要更少的 cpu 周期. 例如, 整型比字符串操作的代价更低, 因为字符集和校对规则(排序规则) 使得字符的比较比整型更加复杂.
- 尽量避免 NULL
很多表都可以包含为 NULL 的列, 即使 应用程序不需要也是如此的, 这是因为 NULL 是列的默认属性(定义表结构是, 没有指定 NOT NULL 默认都是 DEFAULT NULL 的), 通常情况下, 最好指定列为 NOT NULL, 除非真的需要存储 NULL 值.
如果查询的中包含可为 NULL 的列, 对于 MySQL 来说通常更加难优化(对于客户端来说同样如此, 其他在 golang 中, 如果查询的结构的列中有 NULL 的, 需要使用
type NullString struct {
String string
Valid bool // Valid is true if String is not NULL
}
这样类型的才能获取到 NULL 值), 因为可为 NULL 的列使得索引, 索引统计, 值比较都更加复杂. 可为 NULL 的列, 会使用更多的存储空间, 在 MySQL 里需要特殊的处理. 当可以为 NULL 的列被索引时, 每个索引记录需要一个额外的字节, 在 MyISAM 里面甚至还可能导致固定大小的索引(例如只有一个整数列的索引)变成可变大小的索引.
总结: 列可以为 NULL 时并且为索引时, 欸外需要一个的字节来保存 NULL
类型, 参考 MySQL doc
varchar(), char() 的区别
varchar() 类型, 需要欸外的两个字节来保存真正的长度
范式和反范式
没有银弹, 根据真实的情况来
总结
- 尽量避免过度设计, 例如会导致极其复杂查询的 schema 设计, 或者有很多列的表的设计(相对来说)
- 使用小而且简单的合适数据类型, 除非真的需要, 否则应该尽量不用 NULL 作为默认值
- 尽量使用相同的数据类型存储类似或者相关的值, 尤其是在关联条件中使用的列 (一般来说, 主键, 外键的类型设置为一样的)
- 注意可变长字符串, 尤其在临时表或者排序时, 可能导致悲观地按照最大长度的内存分配内存.
- 尽量使用整型定义表示列(这个和 B-Tree 索引的数据结构有很多的关系, 说白了就是减少索引的内存占用和索引的比较性能)
- 避免使用 MySQL 已经遗弃的特性, 例如指定浮点数的精度, 或者整数的显示宽度
- 小心使用 ENUM 和 SET.