字符集的选择
字符集直接决定了数据在mysql中的存储编码方式,由于同样的内容使用不同字符集表示所占用的空间大小会有较大的差异,所以通过使用合适的字符集,可以帮助我们尽可能减少数据量,进而减少IO操作次数。
1.纯拉丁字符能表示的内容,没必要选择 latin1 之外的其他字符编码,因为这会节省大量的存储空间。
2.如果我们可以确定不需要存放多种语言,就没必要非得使用UTF8或者其他UNICODE字符类型,这回造成大量的存储空间浪费。
3.MySQL的数据类型可以精确到字段,所以当我们需要大型数据库中存放多字节数据的时候,可以通过对不同表不同字段使用不同的数据类型来较大程度减小数据存储量,进而降低 IO 操作次数并提高缓存命中率。
主键的选择
推荐使用代理主键,不与业务耦合,更容易维护
代理主键:与业务无关的,无意义的数字序列
自然主键:事物属性中的自然唯一标识
一个大多数表,最好是全部表,通用的键策略能够减少需要编写的源码数量,减少系统的总体拥有成本
数据类型优化
1.小数据,好数据
应该尽量使用可以正确存储数据的最小数据类型,更小的数据类型通常更快,因为它们占用更少的磁盘、内存和CPU缓存,并且处理时需要的CPU周期更少
2.避免null
可为null的列在进行sql优化的时候使索引、索引统计和值比较都更加复杂
3.使用更合适的数据类型
1、整型比字符操作代价更低,因为字符集和校对规则是字符比较比整型复杂
2、使用mysql自建类型。比如不能用字符串来存储日期和时间
3、可以使用整型存储IP地址,用INET_ATON()和INET_NTOA函数在这两种表示方法之间转换。优点是存储空间变小,缺点是可读性变差
SELECT INET_ATON(\'192.168.23.4\');
SELECT INET_NTOA(3232241412);
4.TINYINT,SMALLINT,MEDIUMINT,INT,BIGINT分别使用8,16,24,32,64位存储空间。尽量使用满足需求的最小数据类型
5.按照查询速度:char>varchar>text
char长度固定,即每条数据占用等长字节空间;最大长度是255个字符,适合用在身份证号、手机号等定长字符串
varchar可变程度,可以设置最大长度;最大空间是65535个字节,适合用在长度可变的属性
text不设置长度,当不知道属性的最大长度时,适合用text
6.BLOB 和TEXT 值当作一个独立的对象处理。为了存储很大数据而设计的字符串类型,分别采用二进制和字符方式存储。
7.枚举类
有时可以使用枚举类代替常用的字符串类型,mysql存储枚举类型会非常紧凑,会根据列表值的数据压缩到一个或两个字节中,mysql在内部会将每个值在列表中的位置保存为整数,并且在表的.frm文件中保存“数字-字符串”映射关系的查找表
create table enum_test(e enum(\'fish\',\'apple\',\'dog\') not null);--创建表字段为枚举类型
insert into enum_test(e) values(\'fish\'),(\'dog\'),(\'apple\');--插入数据
select e+0 from enum_test;--查询
select * from enum_test where e = 0;--查询
select * from enum_test where e = \'fish\';--查询
8.datetime和timestamp
datetime
占用8个字节
与时区无关,数据库底层时区配置,对datetime无效
可保存到毫秒
可保存时间范围大
不要使用字符串存储日期类型,占用空间大,损失日期类型函数的便捷性
timestamp
占用4个字节
时间范围:1970-01-01到2038-01-19
精确到秒
整型存储
依赖数据库设置的时区
自动更新timestamp列的值
date
占用的字节数比使用字符串、datetime、int存储要少,使用date类型只需要3个字节
使用date类型还可以利用日期时间函数进行日期之间的计算
date类型用于保存1000-01-01到9999-12-31之间的日期
范式和反范式
不必严格遵守范式和反范式,根据实际业务实际分析。必要的冗余字段可以减少大量的关联表
范式
优点:
范式化的更新通常比反范式要快
当数据较好的范式化后,很少或者没有重复的数据
范式化的数据比较小,可以放在内存中,操作比较快
缺点:
通常需要进行关联
反范式
优点:
所有的数据都在同一张表中,可以避免关联
可以设计有效的索引
缺点:
表格内的冗余较多,删除数据时候会造成表有些有用的信息丢失
存储引擎的选择
适当的拆分
将有大字段类型如TEXT 或者很大的 VARCHAR类型的大字段,若访问这张表主要不是访问这个字段,将其拆分到另外的独立表中,减少常用数据所占用的存储空间。
这样可以将每个数据块中可以存储的数据条数增加,减少物理 IO 次数,也能提高内存中的缓存命中率。