更小的通常更好
- 更小的通常更快
- 使用不同数据类型的时候,虽然存储的内容是完全一样的(数据大小必然是一样的),但是因为4k对齐的存在,两者实际上占用的空间是不一样的(一个大,一个小)
- 使用不同数据类型的时候一定是有区别的
- ORM能否映射,应该是可以的;这里只是强调在数据库中存储的空间尽量少
简单就好
- 该是什么类型就用什么类型
- 用整型存储ip
- 用mysql自建类型存储日期,而不用字符型
- 整型比字符的操作代价更低,字符的校验规则更复杂
尽量避免使用null
- 数据库中null是否等于null
- 不等于,所以不起作用
- 查询中包含了null,对mysql来说是很难优化的
- 因为可为null的一些列使得索引统计和值的比较都变得复杂
- 包括判断
- 比较
- 优化
- 索引
- 都很麻烦
- 坦白说,可为null的列改为not null带来的性能提升非常小,所以没有必要进行优化
- 之前的项目可为空,就让他空着;假如此时要设计一个数据库,尽量让所有的列不为null
- 实际应用中,不可避免地会使用到null(不可能让用户信息都填满)
- 能不使用null,尽量不使用null,这是最重要的
- 默认值、特殊值要慎重—->字符型可以用空字符串,不能用a之类的,因为他可能出现在用户数据之中
- oracle中有空串吗?mysql是可以的
- 如果能的话(有选择的话),尽量设置为非空not null;不能的话就那样,没有选择设置为null
实际类型的优化
- 类型优化其实很重要
- 类型设计得很好的话,表空间是比较省的
- 设计得不好的话,比如只给类型而不指定长度的时候,默认是int(11)、varchar(255),这样会占用更多的存储空间,这样不好
- 一定要存指定好的长度
- ❓❓❓可以用数据字典???
- sqlsever不知道(用的少???)
- 字段的长度在定义表的时候最好明确规定,虽然没有什么影响
- 用int、varchar等存储的时候都是占的几个字节,只要没有超过类型的范围就行了,那个长度只是显式地定义了一下
- 定义的长度定义的是一个规范,实际上没有什么用,就是规定了最大长度是多少
- 即使超过了但是未超过范围仍然是合理的,但是建议写好,者关乎到一些规范的东西(写死就行了)
- 需要多少就写多少,只是做了一个数据格式的校验,前台输入的时候不要超过那个长度就行了!
- 字符型和DECIMAL有用,而整型和浮点型没有用
- 主要用在严格模式中(比较麻烦,一般不涉及那个东西)
- 在严格模式中很多东西都会受到影响
- 整型特殊—->他与底层实际存储的字节数挂钩,与长度无关
- 而字符型,他的实际存储是与长度相关的
整型
- tinyint、smallint、mediumint、int、bigint的大小分别为8、16、24、32、64位
-
字符型
char
- 最后面的空格会被去掉,而varchar不会
- oracle中仍然会有空格?
- 最大长度255
- 检索效率、写效率比varchar高,以空间换时间(空间范围有限,只能存255,不适合存中文字符或者其他特殊字符)
- 一般没有什么意义,因为在程序中会使用trime去掉空格再比较
- varchar
- varchar(5)和varchar(255)保存同样的内容,硬盘存储空间相同,但内存空间占用不同,是指定的大小
- 一页是4kb,从磁盘中读取数据时,一下子是读取页的整数倍
- 4k对齐,os默认的,好像也可以自己设置
- 磁盘预读
- 内存占用空间比实际大小要大一些,除非大小刚好是4k的整数倍
- 4.2k—->8k;9m—->12m
- 4k非常有用,在索引中也很重要,读索引时读的是整个4k中的数据
- text
- 一般不会用
- 可以这么用但是一般不建议
- 可以把json存在里面???
- 有富文本编辑器(编译器?)
- 完全可以放到一个ftp文件系统中,要读取的话直接读ftp中的文件就行了,不用再访问数据库了,因为一般情况下(跨数据库的时候?)访问数据库的时候会有一些IO的问题,而且有缓存的话还要将其进行缓存,太麻烦了
- 一般不要用他,用varchar和char就够了
- blob
- 一般不会用
- 可以这么用但是一般不建议
- 有富文本编辑器(编译器?)
- varchar2(oracle中的数据类型)
时间戳
- 时间戳有多种类型,选择哪一个的时候会关乎我们的精度
- datetime
- timestamp
- date
使用枚举代替字符串类型
- mysql存储枚举类型会非常的紧凑,会根据列表值的数据压缩到一个或者两个字节之中,mysql内部会将每个值在列表中的位置保存为整数,并且在表的.frm文件中保存“数字-字符串”映射关系的查找表
- 比如保存性别:男和女,假如存成0和1,那么还要在业务层进行转换
- 假如用枚举可以将这个转换过程放到数据库层面进行
- 底层存储枚举类型的时候,实际上存储的是整型
- select e+0 from table;
- 还可以进行排序,排序是按照枚举字符串所对应的整型值进行排序的,这个整数值与定义表时定义枚举的具体值时的顺序有关!
- ORM框架不报错吗???应该没问题
- 枚举类型的where条件可以用整型也可以用字符串类型
- fish、apple、dog都是显式形式
- 是读取数据的时候直接通过.frm转换过来的,实际中存储的是整型
- 枚举类型的枚举值千万不要命名为数字,例如将枚举型分别定义为“1”“2”“3”没必要就是找事
- 学的是优化点,不是钻牛角尖和抬杠
- 枚举很常用,判断业务表中有些列就是那几个固定的很常用的值,这样的话最好使用枚举,可以提高效率
- 国家省市区、自己的心情状态就可以写死
- 或者直接用数字整型表示枚举型,可以节省很多空间(提高效率,违背命名规范?)
特殊类型
- ip地址
- 通常用varchar(15)来存储ip地址,但是这样不行,效率太低
- 可以用32位无符号整数来进行存储、判断与比较
- inet_aton和inet_ntoa
- 第一个将字符型转换为整型,第二个将整型转换为字符型
- 整数范围—->21亿
合理使用范式和反范式
范式
- 大型项目的表设计要遵循三范式
- 三范式是为了解决数据冗余问题
- 优点:
- 范式更新通常比反范式快
- 很少有重复数据
- 范式化的数据比较小,可以直接放在内存中,操作比较快
- 缺点:
- 通常情况下需要进行关联操作
- 一张表的数据分成多张表就需要进行连接了
- 阿里规范中:假如有超过三张表的时候禁止使用join的方式
- why?
- 因为三张表join的时候,数据量比较大的话,join的过程会很慢
- 实际问题具体情况具体分析,不要不管三七二十一就按阿里规范来
- 因为有可能项目中的数据量达不到那种层次,join也会很快,不会受什么影响的,没必要纠结
- why?
反范式
- 在有些场景中可能需要冗余一部分的数据(反范式)
- 范式更新通常比反范式快
- 优点:
- 所有的数据都在一张表中,可以避免关联
- 可以设计一个有效的索引
- 缺点:
- 表格内的冗余数据比较多,删除数据的时候会造成表中有些有用信息丢失
范式和反范式进行一个衡量选择即可
- 没必要一定按照某一个标准来
- 实际情况具体分析
- 范式和反范式混合使用、配合使用
应用场景
- 尽量避免全排序,因为全排序要将表全部放到内存中去,效率太低了
- 可以采用数据直接放到一张表里面不用再做join关联的方式了或者采用索引的方式进行排序
- mysql中索引底层的数据结构是b+树,b+树本身就是一棵有序树,只要在相应列上建立索引,就可以按照当前列直接进行排序,就不需要自己放到内存里面再进行一次排序了
- 为什么写了limit之后就不用写order by了,为什么写了limit之后order by就失效了
- 就是因为用到了索引的查询—->效率比较高
- 不需要count统计,直接查询缓存衍生值
- 需要考虑做count和update的成本高低问题
- 做一个选择
- 设计表的时候,范式或者反范式都行,不要严格限制,可以两种方式结合使用
- 约定大于规范
- 没有哪里说设计表的时候一定要按范式来,可以自由点
- 需求就要这样设计,不违反规则即可
- 空间换时间
- 合理选择即可,没必要说一定要遵循三范式的原则
三范式
- 列不可分
- 不存在传递依赖
- 其他列的值必须唯一依赖主键值