mysql的schema和数据类型优化

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: mysql的schema和数据类型优化

前言:

优秀的设计和逻辑是高性能的基本保障,我们来看下关于mysql使用schema和数据类型优化的一些建议和原则。

1.选择优化的数据类型的常用规则

  • 更小的通常更好
    一般选择更小的数据类型能满足业务场景的需求,小的数据类型意味着更小的cpu开销,更小的内存,储存空间的使用,可以提高效率。
  • 简单的数据类型
    整型的数据类型比字符型,浮点型数据要来的简单,处理起来也更方便。
  • 尽量避免使用NULL

如果不是必须要储存NULL值的话,一般情况下都要指定列为NOT NULL。可以为NULL的列会使用更多的空间,使用的时候也需要消耗额外的资源。
而且当列时NULL的时候,建立索引也需要额外的开销,并且上面的唯一索引不会将NULL算为唯一的,多条NULL的数据都可以保存成功,会对数据的唯一性也造成干扰。

2. 选择数据类型的优化

2.1 整数类型 :

1.mysql的证书类型:TINYINT(8),SMALLINT(16),MEDIUMINT(24),INT(32),BIGINT(64)后面小括号中的数字是占用的存储空间。
2.unsigned不会影响mysql的储存空间,有符号的INTYINT储存范围是-128~127,无符号的TINY能储存0~255。总共包含的数值尺寸(总共256个数字),
但是数据的范围是有变化的。可以根据具体的场景来设置最合适的范围。
3.对于整数类型而言int(1)和int(20)没有区别,计算和储存都不会有影响,只是可能会影响一些mysql的客户端工具显示字符的个数。
注:这里稍微扯一点题外话,TINYINT设置为1和大于1的数字,会影响mybatis generator逆向生成java bean和xml的时候的数据格式。
TINYINT(1)会对应Boolean类型,TINYINT(n) n>1的话显示的是Byte类型。

2.2 实数类型

1.mysql内部使用DOUBLE作为浮点型运算的类型,DECIMAL只是一种储存格式,在计算的时候也会转换为DOUBLE。DOUBLE和DECIMAL,mysql5.0之后对DECIMAL进行了优化,可以支持高精度的计算,但是会比较消耗性能,DOUBLE计算更快但是可能会丢失经度。
2.因为DECIMAL使用了更多的空间和计算的消耗,所以只在对小数进行精确计算的时候才使用DECIMAL,正常储存浮点数不用计算的话,DOUBLE就够了。
3.还有一种方式就是使用整型来储存浮点数,将要储存的浮点数乘以小数的位数变成整型在储存起来。这样可以避免浮点储存计算不精确和DECIMAL计算消耗大的问题。

2.3 字符串类型

1.varchar可能是我们用的最多的类型了,它是可变长度的,varchar(1000)如果只用到了10个字节,实际上储存空间上就用了11个字节,一个字节用来记录字符串的长度,当字符串超过255个字节的时候会使用两个字节。另一个char是不可变的字符串,
如果是char(10),实际上使用了11个字节,1个用来记录字符串的长度。
2.不过因为varchar是可变长的,如果字段更新操作时变长了,会需要额外的开销,所以varchar最合适的场景是字符串最大长度比平均长度大很多,而且更新不频繁。
3.char在储存字符串的时候,会把末尾的空格给去掉,如果是'abc  ',实际使用和储存时都是'abc'。
4.如果设置了ROW_FORMAT=FIXED,即使是varchar也是会使用定长字节来储存的
5.之前从来没有用过mysql的枚举类型数据,看了书才知道还有枚举类型,平时基本上都是用的java建的枚举类使用比较方便。mysql的枚举类底层储存的也是整数,估计是做了
hash的操作给映射成整数了,不过如果mysql的枚举要联表查询的话性能消耗比较高,可能这也是不太常用的原因之一吧。

2.4 日期类型 官方文档链接

1.datetime格式范围大概是从1001年-9999年(如果超过了9999年会怎么样呢?会报错的),timestamp这个是从1970年1月1日开始的,而且范围贼小到2038-01-19 03:14:07,
因为我们是东八区所以可以在加八个小时。  
所以最好不要用时间戳,这还有18年可能你写的程序就会因为时间格式超过了范围而报错。
2.timestamp在插入时没有值会默认写入一个当前时间戳的值,切不能为null。
3.mysql数据库支持的时间粒度是秒,如果要储存更小粒度的时间,可以使用mysql的分支MariaDB,或者使用BIGINT,DOUBLE处理后来储存时间戳。

2.5 位数据类型

1.set和bit都可以用来存储true/false的值,不是很常用。例如保存某个数据的状态可以用bit,不过一般用tinyint会更常见一些。

2.6 选择标识符

1.为标识列选择合适的数据类型很重要。整数型 > 字符串 > set/enum

2.7 特殊类型数据

1.这里谈到一个例子IPV4,人们经常用VARCHAR(15)来储存,实际上去除掉符号点,是一个无符号的整数。用整数来储存更加合适,
mysql提供了INET_ATON()和INET_NOTA()来转换。

3.schema设计的陷阱

3.1 太多的列

mysql储存引擎和服务层之前拷贝数据的时候,会将缓存的内容解码为各个对应的列。但是
一张表如果列宽很长,几千个列这样,实际使用的时候有时候只用到了小部分数据,这样解码效率就很低,查询也会变得很慢。

3.2 太多的关联

mysql限制了每个关联最多61张表(当然我觉得是够用了,要是一个关联能关联61张表,那就设计上很有问题了)。经验法则,一个查询要想又快又能保持并发性良好,关联最好不超过12张表。

3.3 全能的枚举

一个枚举如果包含了太多的数据,当成了字典来使用的话,当要进行修改的使用因为是阻塞操作,会导致使用这个枚举的业务都停下来。

3.4 变相的枚举

当使用set来代替enum来使用的时候,比如记录是true/false,如果有很多个这样的值,用set来储存容易导致混乱,最好用enum。

3.5 NULL的替代方案

前面说了尽量不使用NULL,我们可以使用-1,0,空字符串来代替。但是不要每个地方都这样用,有时候使用替代方案可能会导致编写代码和业务场景变得更加复杂,比如其他部门都用NULL,我们使用-1,这样很多调用部分都得做出相应的修改。
在具体的场景可以具体分析,并不是说NULL就不能用了。
相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
9天前
|
SQL 关系型数据库 MySQL
深入解析MySQL的EXPLAIN:指标详解与索引优化
MySQL 中的 `EXPLAIN` 语句用于分析和优化 SQL 查询,帮助你了解查询优化器的执行计划。本文详细介绍了 `EXPLAIN` 输出的各项指标,如 `id`、`select_type`、`table`、`type`、`key` 等,并提供了如何利用这些指标优化索引结构和 SQL 语句的具体方法。通过实战案例,展示了如何通过创建合适索引和调整查询语句来提升查询性能。
77 9
|
13天前
|
缓存 关系型数据库 MySQL
MySQL 索引优化以及慢查询优化
通过本文的介绍,希望您能够深入理解MySQL索引优化和慢查询优化的方法,并在实际应用中灵活运用这些技术,提升数据库的整体性能。
54 18
|
12天前
|
缓存 关系型数据库 MySQL
MySQL 索引优化以及慢查询优化
通过本文的介绍,希望您能够深入理解MySQL索引优化和慢查询优化的方法,并在实际应用中灵活运用这些技术,提升数据库的整体性能。
18 7
|
11天前
|
缓存 关系型数据库 MySQL
MySQL 索引优化与慢查询优化:原理与实践
通过本文的介绍,希望您能够深入理解MySQL索引优化与慢查询优化的原理和实践方法,并在实际项目中灵活运用这些技术,提升数据库的整体性能。
41 5
|
1月前
|
关系型数据库 MySQL Java
MySQL索引优化与Java应用实践
【11月更文挑战第25天】在大数据量和高并发的业务场景下,MySQL数据库的索引优化是提升查询性能的关键。本文将深入探讨MySQL索引的多种类型、优化策略及其在Java应用中的实践,通过历史背景、业务场景、底层原理的介绍,并结合Java示例代码,帮助Java架构师更好地理解并应用这些技术。
33 2
|
3天前
|
存储 Oracle 关系型数据库
数据库传奇:MySQL创世之父的两千金My、Maria
《数据库传奇:MySQL创世之父的两千金My、Maria》介绍了MySQL的发展历程及其分支MariaDB。MySQL由Michael Widenius等人于1994年创建,现归Oracle所有,广泛应用于阿里巴巴、腾讯等企业。2009年,Widenius因担心Oracle收购影响MySQL的开源性,创建了MariaDB,提供额外功能和改进。维基百科、Google等已逐步替换为MariaDB,以确保更好的性能和社区支持。掌握MariaDB作为备用方案,对未来发展至关重要。
13 3
|
3天前
|
安全 关系型数据库 MySQL
MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!
《MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!》介绍了MySQL中的三种关键日志:二进制日志(Binary Log)、重做日志(Redo Log)和撤销日志(Undo Log)。这些日志确保了数据库的ACID特性,即原子性、一致性、隔离性和持久性。Redo Log记录数据页的物理修改,保证事务持久性;Undo Log记录事务的逆操作,支持回滚和多版本并发控制(MVCC)。文章还详细对比了InnoDB和MyISAM存储引擎在事务支持、锁定机制、并发性等方面的差异,强调了InnoDB在高并发和事务处理中的优势。通过这些机制,MySQL能够在事务执行、崩溃和恢复过程中保持
20 3
|
3天前
|
SQL 关系型数据库 MySQL
数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog
《数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog》介绍了如何利用MySQL的二进制日志(Binlog)恢复误删除的数据。主要内容包括: 1. **启用二进制日志**:在`my.cnf`中配置`log-bin`并重启MySQL服务。 2. **查看二进制日志文件**:使用`SHOW VARIABLES LIKE 'log_%';`和`SHOW MASTER STATUS;`命令获取当前日志文件及位置。 3. **创建数据备份**:确保在恢复前已有备份,以防意外。 4. **导出二进制日志为SQL语句**:使用`mysqlbinlog`
23 2
|
17天前
|
关系型数据库 MySQL 数据库
Python处理数据库:MySQL与SQLite详解 | python小知识
本文详细介绍了如何使用Python操作MySQL和SQLite数据库,包括安装必要的库、连接数据库、执行增删改查等基本操作,适合初学者快速上手。
119 15
|
10天前
|
SQL 关系型数据库 MySQL
数据库数据恢复—Mysql数据库表记录丢失的数据恢复方案
Mysql数据库故障: Mysql数据库表记录丢失。 Mysql数据库故障表现: 1、Mysql数据库表中无任何数据或只有部分数据。 2、客户端无法查询到完整的信息。