《高性能Mysql》读书笔记之Schema与数据类型优化

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 《高性能Mysql》读书笔记之Schema与数据类型优化

一、选择优化的数据类型

原则

  • 使用可以正确存储的最小数据类型

小的数据类型占用更少的磁盘、内存和CPU缓存,并且处理时需要的CPU周期也更少

  • 选择简单的数据类型

简单的数据类型通常需要更少的CPU周期,整数比字符操作代价更低

  • 尽量避免NULL

通常情况下最好设置指定列为NOT NULL,除非真的需要存储NULL值

  1. NULL会使用更多的存储空间,再MYSQL中需要特殊处理
  2. 当可为NULL的列被索引时,每个索引记录需要一个额外的字节
  3. 在MYSQL中还可能导致固定大小的索引变成可变大小的索引

1. 整数类型

基本属性
类型 占用存储空间 存储范围
TINYINT 8 -27~27
SMALLINT 16 -215~215
MEDUIMINT 24 -223~223
INT 32 -231~231
BIGINT 64 -263~263
注意点
  1. 整数类型有可选的 UNSIGNED 属性,表示不允许负值,这样可以使正数的上限提高一倍

TINYINT 存储范围是 -128~127 ,TINYINT UNSIGNED 存储范围是 0 ~128

  1. 有符号和无符号类型使用相同的存储空间,并具有相同的性能
  2. MYSQL可以位整数指定宽度,例如INT(11),对大多数应用是没有意义的:它不会限制值的合法范围,只是规定了MYSQL的一些交互工具用来显示的字符个数。
  3. 对于存储和计算来说,INT(11)和INT(20)是相同的

2. 实数类型

DECIMAL
  1. DECIMAL类型用于存储精确的小数
  2. CPU不支持对DECIMAL的直接计算,CPU直接支持原生浮点计算,所以浮点运算更快
  3. MYSQL会将数字打包到一个二进制字符串中(每4个字节存储9个数字);如DECIMAL(18,9)小数两边各存储9个数字,一共使用9个字节
  4. MYSQL的DECIMAL类型支持最多65个数字
  5. 在计算中DECIMAL会转换位DOUBLE
选择
  1. FLOAT使用4字节存储,DOUBLE使用8字节存储,相比DECIMAL占用更少存储空间
  2. 在要求确保数据精确情况下,数据量小使用DECIMAL,数量量大使用BIGINT存储

3. 字符串类型

比较 VARCHAR CHAR
存储内容 存储可变长字符串 存储定长字符串
存储空间 列的最大长度小于255字节,则使用1个字节记录字符串长度,否则使用2个字节 根据字符串长度分配足够空间
适合场景 字符串列的最大长度比平均长度大得多 ; 列的更新很少,没有碎片问题;使用了像UTF-8这样复杂的字符集,每个字符集都是用不同字节存储 适合存储很短的字符串,或者所有值都接近同一个长度
注意点 UPDATE比原来更长时,数据库会做额外工作CHAR会根据需要采用空格进行填充以方便比较
比较 BLOG TEXT
区别 存储二进制字符;无字符集和排序规则 有字符集和排序规则
相同点 MYSQL把BLOG和TEXT当作单独对象处理,当BLOG和TEXT值太大时,Innodb会使用专门外部区域存储,每个值在行内用1~4个字节存储一个指针,然后再外部存储实际的值
使用枚举代替字符串类型
  1. 枚举使用整数存储而不是字符串
  2. MYSQL存储的是每个值在列表中的位置,而不是实际的值,实际的值存在 .frm 文件中保存"数字 - 字符串"映射关系
  3. 枚举按照内部存储的整数而不是定义的字符串进行排序,所以创建枚举的时候得按顺序存放
  4. 可以在查询中使用FIELD()显示指定排序顺序,但会导致无法利用索引消除排序
  5. 尽量不要用枚举存储整数,容易导致混乱
  6. 枚举不适合未来可改变的字符串,除非能接受只在列表末尾添加元素

4. 日期和时间类型

比较 DATETIME TIMESTAMP
范围 1001~9999年 保存1970年1月1日午夜以来的秒数,和Unix时间戳相同,只能表示1970~2038年
精度
格式 将日期和时间封装到格式为YYYYMMDDHHMMSS的整数中,与时区无关 默认NOT NULL,默认为当前时间
存储空间 8个字节 4个字节

5. 位数据类型

BIT
  1. 存储一个或多个true/false值
  2. 最大存储64位
  3. Memory和Innodb,为每个BIT使用一个足够存储的最小整数类型存放,所以不能节省存储空间
  4. MYSQL把BIT当作字符串类型而不是整数类型
  5. 谨慎使用BIT类型,大部分应用避免使用此类型
SET
  1. 在MYSQL内部是一个打包的位的集合表示
  2. 改变列的定义的代价很高,需要alter table 和 枚举增长一样一样的

二、MySQL Schema 设计中的陷阱

  1. 太多的列
  2. 太多的关联

单个查询最好在12个表以内做关联

  1. 全能的枚举即过度使用枚举
  2. 变相的枚举即避免滥用SET,考虑使用枚举代替集合

三、范式和反范式

范式的优点

  • 范式化的更新操作通常比反范式化要快
  • 当数据较好的范式化时,就只要很少或这没有重复数据,所以只需要修改更少的数据
  • 范式化的表通常更小,可以更好的放在内存里,所以执行操作会更快
  • 很少有多余的数据意味着检索列表数据时更少需要DISTINCT或者GROUP BY语句

范式的缺点

  • 范式之间的关联比较复杂

反范式的优点

  • 数据都在一张表中,避免了关联
  • 避免随机IO,当整表查询的时候,基本上是顺序IO
  • 冗余的表处理某些业务时候非常方便

混用范式化和反范式化

  • 实际环境中不可能完全范式化或反范式化

四、缓存表和汇总表

缓存表 | 表示存储那些可以比较简单地从schema其它表获取(但获取速度比较慢)数据的表

汇总表 | 保存使用 GROUP BY 语句聚合数据的表

1.物化视图

物化视图实际上是预先计算并且存储在磁盘上的表,可以通过各种各样的策略刷新和更新

Mysql不支持原生物化视图

这里推荐开源工具 Flexviews

组成
  • 变更数据抓取功能,可以读取服务器的二进制日志并且解析相关行的变更
  • 一系列可以帮助创建和管理视图的定义的存储过程
  • 一些可以应用变更到数据库中的物化视图的工具

2.计数器表

  • 使用单一的字段,会有全局锁
  • 在表中建多个例如100个技术行,每次随机更新其中的某一行,可以减少并发

五、加快ALTER TABLE操作的速度

ALTER TABLE操作是新建一张表,将旧表所需数据查出插入到新表中,然后删除旧表,这种操作有时会持续数小时

优化

  1. 现在一台不常用的服务器上进行ALTER TABLE 操作,然后和提供服务的主库进行切换
  2. 用要求的表结构创建一张和原表无关的新表,然后通过重命名和删表方式交换量表数据
  3. 直接修改 .frm 表而不涉及表数据

可能不需要重建表的一些操作

  • 移除(非增加)一个列的AUTO_INCREMENT属性
  • 增加、移除或更改ENUM和SET常量。如果移除的是已经有行数据用到其他值的常量,查询将会返回一个空字符串

实现方式

原则是创建一个新的frm文件替换原来的frm文件

  1. 创建一张有相同结构的表,并进行所需要的修改(例如增加ENUM常量)
  2. 执行FLUSH TABLES WITH READ LOCK。这将会关闭所有正在使用的表,并且进制任何表被打开
  3. 交换.frm文件
  4. 执行UNLOCK TABLES 来释放第二步的锁

快速创建MyISAM索引

TIP:会有很大风险,不是官方操作,做之前先备份数据

  1. 用需要的表结构创建一张表,但是不包括索引
  2. 载入数据到表中以构建.MYD文件
  3. 按照需要的结构创建另外一张空表,这次要包含索引。这会创建需要的 .frm.MYI 文件
  4. 获取读锁并刷新表
  5. 重命名第二张表的 .frm.MYI 文件,让MySQL认为是第一张表的文件
  6. 释放读锁
  7. 使用ALTER TABLE来重建表的索引。该操作会通过排序来构建所有索引,包括唯一索引

总结

  1. 避免过度设计
  2. 避免NULL值
  3. 使用小而简单的适合的数据类型
  4. 尽量使用相同的数据类型存储相似或相关的值,尤其是在关联条件中使用的列
  5. 注意可变长字符串,其在临表和排序时可能导致最大长度分配内存
  6. 尽量使用整型定义标识列
  7. 避免使用MYSQL已经遗弃的特性
  8. 小心使用ENUM和SET
  9. 范式是好的,但反范式有时也是必须的,并且能带来好处
    10.ALTER TABLE是痛苦的操作,因为大部分情况下会锁表并重建整张表

参考书目

《高性能MySQL》

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
12天前
|
SQL 关系型数据库 MySQL
MySQL慢查询优化、索引优化、以及表等优化详解
本文详细介绍了MySQL优化方案,包括索引优化、SQL慢查询优化和数据库表优化,帮助提升数据库性能。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
MySQL慢查询优化、索引优化、以及表等优化详解
|
16天前
|
缓存 监控 关系型数据库
如何优化MySQL查询速度?
如何优化MySQL查询速度?【10月更文挑战第31天】
44 3
|
19天前
|
缓存 关系型数据库 MySQL
如何优化 MySQL 数据库的性能?
【10月更文挑战第28天】
43 1
|
26天前
|
NoSQL 关系型数据库 MySQL
MySQL与Redis协同作战:百万级数据统计优化实践
【10月更文挑战第21天】 在处理大规模数据集时,传统的单体数据库解决方案往往力不从心。MySQL和Redis的组合提供了一种高效的解决方案,通过将数据库操作与高速缓存相结合,可以显著提升数据处理的性能。本文将分享一次实际的优化案例,探讨如何利用MySQL和Redis共同实现百万级数据统计的优化。
68 9
|
20天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第27天】本文深入探讨了MySQL的索引策略和查询性能调优技巧。通过介绍B-Tree索引、哈希索引和全文索引等不同类型,以及如何创建和维护索引,结合实战案例分析查询执行计划,帮助读者掌握提升查询性能的方法。定期优化索引和调整查询语句是提高数据库性能的关键。
97 1
|
26天前
|
NoSQL 关系型数据库 MySQL
MySQL与Redis协同作战:优化百万数据查询的实战经验
【10月更文挑战第13天】 在处理大规模数据集时,传统的关系型数据库如MySQL可能会遇到性能瓶颈。为了提升数据处理的效率,我们可以结合使用MySQL和Redis,利用两者的优势来优化数据查询。本文将分享一次实战经验,探讨如何通过MySQL与Redis的协同工作来优化百万级数据统计。
56 5
|
1月前
|
存储 关系型数据库 MySQL
优化 MySQL 的锁机制以提高并发性能
【10月更文挑战第16天】优化 MySQL 锁机制需要综合考虑多个因素,根据具体的应用场景和需求进行针对性的调整。通过不断地优化和改进,可以提高数据库的并发性能,提升系统的整体效率。
58 1
|
1月前
|
缓存 关系型数据库 MySQL
一文彻底弄懂MySQL优化之深度分页
【10月更文挑战第24天】本文深入探讨了 MySQL 深度分页的原理、常见问题及优化策略。首先解释了深度分页的概念及其带来的性能和资源问题。接着介绍了基于偏移量(OFFSET)和限制(LIMIT)以及基于游标的分页方法,并分析了它们的优缺点。最后,提出了多种优化策略,包括合理创建索引、优化查询语句和使用数据缓存,帮助提升分页查询的性能和系统稳定性。
104 1
|
21天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第26天】数据库作为现代应用系统的核心组件,其性能优化至关重要。本文主要探讨MySQL的索引策略与查询性能调优。通过合理创建索引(如B-Tree、复合索引)和优化查询语句(如使用EXPLAIN、优化分页查询),可以显著提升数据库的响应速度和稳定性。实践中还需定期审查慢查询日志,持续优化性能。
49 0
|
30天前
|
存储 监控 关系型数据库
MySQL并发控制与管理:优化数据库性能的关键
【10月更文挑战第17天】MySQL并发控制与管理:优化数据库性能的关键
132 0
下一篇
无影云桌面