持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第11天,点击查看活动详情
面试官:除了索引和执行计划外,你还了解哪些调优方式?
数据类型优化
- 更小的通常更好。
- 简单就好。
- 尽量避免null。
实际细则
字符和字符串类型
varchar
- 使用最小的符合需求的长度。
- varchar(n) n<=255使用额外一个字节保存长度,否则使用额外两个字节保存长度。
- varchar(5)和varchar(255)保存同样的内容,硬盘存储空间相同,但内存空间占用不同,是指定的大小。
- varchar在mysql5.6之前变更长度,或者从255以下变更到255以上时,都会导致锁表。
应用场景
- 存储长度波动较大的数据。
- 字符串很少更新的场景,每次更新后都会重新计算并使用额外的存储空间保存长度。
- 适合保存多字节字符,如:汉字。
char
- 最大长度255。
- 会自动删除末尾的空格。
- 检索效率和写效率比varchar更高,空间换时间
应用场景
- 存储长度波动不大的数据。
- 存储短字符串,经常更新的字符串。
datetime和timestamp
datetime
- 占用8个字节。
- 与时区无关,数据库底层时区配置对datetime无效。
- 可保存到毫秒。
- 可保存时间范围大。
- 不要使用字符串存储日期类型,占用空间大,损失日期类型函数的便捷性。
timestamp
- 占用4个字节。
- 时间范围:1970-01-01 - 2038-01-19。
- 精确到秒。
- 采用整型存储。
- 依赖数据库设置的时区。
- 自动更新timestamp列的值。
data
- 占用3个字节。
- 可以利用日期时间函数进行日期之间的计算。
- date类型用于保存1000-01-01 - 9999-12-31之间的日期。
合理的使用范式和反范式
范式
优点
- 范式化的更新通常比反范式要快。
- 当数据较好的范式化后,很少或者没有重复的数据。
- 范式化的数据比较小,可以放在内存中,操作比较快。
缺点
通常需要进行关联。
反范式
优点
- 所有的数据都在同一张表中,不需要关联。
- 可以有效的设计索引。
缺点
表格内冗余比较多,删除数据时会造成表有些有用的信息丢失。
注意
在企业中很少能做到严格意义上的范式或者反范式,一般需要混合使用
- 在一个网站实例中,这个网站,允许用户发送消息,并且一些用户是付费用户。现在想查看付费用户最近的10条信息。在user表和message表中都存储用户类型(account_type)而不用完全的反范式化。这避免了完全反范式化的插入和删除问题,因为即使没有消息的时候也绝不会丢失用户的信息。这样也不会把user_message表搞得太大,有利于高效地获取数据。
- 另一个从父表冗余一些数据到子表的理由是排序的需要。
- 缓存衍生值也是有用的。如果需要显示每个用户发了多少消息(类似论坛的),可以每次执行一个昂贵的自查询来计算并显示它;也可以在user表中建一个num_messages列,每当用户发新消息时更新这个值。
主键的选择
代理主键
与业务无关的,无意义的数字序列。
自然主键
事物属性中的自然唯一标识。
推荐使用代理主键
- 它们不与业务耦合,因此更容易维护。
- 通用的主键策略能减少需要编写的源码数量,减少系统的总体拥有成本。
字符集的选择
- 纯拉丁文能表示的内容,没必要选择latin1之外的其他字符编码,这会节省大量的存储空间。
- 如果我们确定不需要存放多种语言,就没必要非选择使用UTF8或其他UNICODE字符类型,这会造成大量的存储空间浪费。
- MySQL的数据类型可以精确到字段,当我们需要大型数据库中存放很多字节数据的时候,可以通过对不同表不同字段使用不同数据类型来较大程度的减少数据存储量,进而降低IO操作次数并提高缓存命中率。
适当的荣誉数据
- 被频繁引用且只能通过join 2张(或者更多)大表的方式才能得到的独立小字段。
- 这样的场景由于每次Join仅仅只是为了取得某个小字段的值,Join到的记录又大,会造成大量不必要的10,完全可以通过空间换取时间的方式来优化。不过,冗余的同时需要确保数据的一致性不会遭到破坏,确保更新的同时冗余字段也被更新。