MySQL性能优化策略
在我认为数据的性能优化基于以下三个层面,
1:表结构优化
2:索引优化
3:查询优化
一、表结构优化
在设计表的时候除了基于业务逻辑的规范进行设计以外,对表的结构,例如字段的规划要有良好的选择。
1:更小的通常更好:
一般情况下,应该尽量使用可以正确存储数据的最小数据类型,通常更快,因为它们占用的磁盘、内存和CPU缓存,并且处理时需要的CPU周期更少;
首先我们要知道MySQL的字段类型以及它们各自占用的字节数,以便于做出最优的选择
数值数据类型:
类型 | 大小 | 范围(有符号) | 范围(无符号 UNSIGNED) |
TINYINT | 1 字节 |
[-128,127] 即: [-2^7,2^7-1] (下同) 1个字节8位 因为有符号所以符号位占一位 所以是2^(8-1) 或者用补码的思想可以 |
[0,2^8-1] |
SMALLINT | 2 字节 | [-2^15,2^15-1] | [0,2^15-1] |
MEDIUMINT | 3 字节 | [-2^23,2^23-1] | [0,2^24-1] |
INT | 4 字节 | [-2^31,2^31-1] | [0,2^32-1] |
BIGINT | 8 字节 | [-2^63,2^63-1] | [0,2^64-1] |
FLOAT | 4 字节 | (-3.402 823 466 E+38,-1.175 494 351 E-38),0,(1.175 494 351 E-38,3.402 823 466 351 E+38) | 0,(1.175 494 351 E-38,3.402 823 466 E+38) |
DOUBLE | 8 字节 | (-1.797 693 134 862 315 7 E+308,-2.225 073 858 507 201 4 E-308),0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) | 0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) |
DECIMAL |
对DECIMAL(M,D) 如果M>D ,M+2 否则,D+2 |
取决于M N | 取决于M N |
float , double ,decimal的区别
Float
Float又称之为单精度类型:系统提供4个字节用来存储数据,但是能表示的数据范围比整型大的多,大概是10^38;只能保证大概7个左右的精度(如果数据在7位数以内,那么基本是准确的,但是如果超过7位数,那么就是不准确的)
Double
Double又称之为双精度:系统用8个字节来存储数据,表示的范围更大,10^308次方,但是精度也只有15位左右
Decimal定点数:系统自动根据存储的数据来分配存储空间,每大概9个数就会分配四个字节来进行存储,同时小数和整数部分是分开的。
Decimal
是定点数类型:能够保证数据精确的小数(小数部分可能不精确,超出长度会四舍五入),整数部分一定精确
Decimal(M,D):M表示总长度,最大值不能超过65,D代表小数部分长度,最长不能超过30。
总结:
float,double等非标准类型,在DB中保存的是近似值,而Decimal则以字符串的形式保存数值。
在日常开发中浮点数大部分是针对金额,在我接触的开发中一般是用分作为单位,用整型数据(int等)进行存储,这样可以最大程度的避免不精确而导致的金额误差,一笔订单几分钱,上万笔就不是一个小数目了!
字符串类型:
类型 |
大小 |
用途 |
CHAR |
0~255字节 |
定长字符串 |
VARCHAR |
0~255字节 |
变长字符串 |
TINYBLOB |
0~255字节 |
不超过255个字符的二进制字符串 |
TINYTEXT |
0~255字节 |
短文本字符串 |
BLOB |
0~65535字节 |
二进制形式的长文本数据 |
TEXT |
0~65535字节 |
长文本数据 |
MEDIUMBLOB |
0~16777215字节 |
二进制形式的中等长度文本数据 |
MEDIUMTEXT |
0~16777215字节 |
中等长度文本数据 |
LOGNGBLOB |
0~4294967295字节 |
二进制形式的极大文本数据 |
LONGTEXT |
0~4294967295字节 |
极大文本数据 |
CHAR 和 VARCHAR的区别
VARCHAR类型用于存储变长字符串,它会删除末尾的所有空格,它比定长字符串更省空间,因为它仅使用必要的空间(越短的字符串占用越少),VARCHAR会用1或2个额外字节记录字符串长度,VARCHAR节省了空间,因此对性能是有帮助的,但是因为行是变长的,所以每次UPDATE时会重新计算字符串长度,会比定长多做额外工作。因此不是说VARCHAR就一定能提升性能,同样要分使用场景,如果字符串的最大长度比平均长度大很多,且列的更新很少时则适合用VARCHAR。注意InnoDB会把过长的VARCHAR存储为BLOB,通常人们喜欢将IP地址存储为VARCHAR型,其实IP地址是32位二进制表示的,你可以转为十进制表示,因而不是字符串,用小数是将它分为四段便于阅读。
CHAR是定长的,每个列无论字符串长度大小都会分配固定存储空间,CHAR适合存储字符很短,或者所有值接近一个长度时,如存储MD5码、SESSION_ID等,对于经常变更的数据CHAR也比VARCHAR好,再一个是对于非常短的列,CHAR比VARCHAR更节省空间,例如使用CHAR(1)和VARCHAR(1)来存储Y或N时,CHAR需要一个字符,而VARCHAR需要两个,因为还有一个长度字节
BLOB和TEXT区别
它们都是为存储大数据而设计的,BLOB是采用二进制/TEXT采用字符存储。MySQL不能将BLOB和TEXT列全部进行索引(只能做前面某长度的索引,因此在查询SQL时不能用LIKE前模糊匹配,那样就走不到索引了),也不能使用这些索引进行排序。
技巧:使用枚举代替字符串类型,枚举可以把一些重复的字符串存储成一个预定义的集合,MySQL在存储枚举时非常紧凑,MySQL在列中保存值为枚举中的位置整数。枚举最不好的是字符串是固定的,添加或删除必须使用ALTER TABLE。因此对于未来会改变的字符串,使用枚举不是一个好主意,除非能接受在枚举末尾添加元素,由于枚举有一个映射转换过程,所以枚举虽然能减少存储空间,但是也会增加一些额外开销
日期和时间类型:
类型 |
大小(字节) |
范围 |
格式 |
用途 |
DATE |
3 |
1000-01-01~9999-12-31 |
YYYY-MM-DD |
日期值 |
TIME |
3 |
-838:59:59~838:59:59 |
HH:MM:SS |
时间值或持续时间 |
YEAR |
1 |
1901/2155 |
YYYY |
年份值 |
DATETIME |
8 |
1000-01-01 00:00:00~9999-12-31 23:59:59 |
YYYY-MM-DD HH:MM:SS |
日期和时间值 |
TIMESTAMP |
4 |
1970-01-01 00:00:00~2037年某时 |
YYYYMMDD HHMMSS |
混合日期和时间值,时间戳 |
DATETIME和TIMESTAMP的区别
DATETIME:这个类型能保存1001到9999年,精度为秒,与时区无关,使用8个字节存储,存储格式封装为YYYYMMDDHHMMSS的整数,因此它是一种可排序的类型,显示时以ANSI标准定义的日期和时间表示方法显示。
TIMESTAMP:它保存了从1970年1月1日午夜以来的秒数,也就是常说的时间戳,它使用4个字节来存储,依赖于时区。除了特殊情况外,通常我们应该尽量使用TIMESTAMP,因为它比DATETIME更省空间,现实中有些人喜欢使用int来存储时间戳,这并不会带来任何收益,用整数保存时间戳不方便,因为取出来之后还需要程序转换下,所以不推荐这样做
2:简单就好
简单的数据类型操作通常需要更少的CPU周期。
例如,整型比字符操作代价更小,因为字符集和校对规则(排序规则)使它比整型更复杂。
此外MySQL中有时间的数值类型,就不需要用时间戳的形式进行存储(除非在特定的业务内)
3:尽量避免null
null列使得索引统计和值比较都更复杂,null列会使用更多的存储空间,在MySQL里也需要特殊处理,当索引列是NULL,每个索引记录需要一个额外的字符。
例如:定义一个数据id为INT型,由上图我们可以知道INT型的存储空间为4个字节,如果设置为not null 存储空间依旧为4个字节,如果设置为null存储空间就会变成4+1即5个字节
如果索引的字段是null的,索引的存储空间也会+1个字节
二、索引优化
三、查询优化
部分参考来源:
https://blog.csdn.net/u012717614/article/details/79861750
《高性能MySQL》
- Docker系列教程16-network命令
- 【LEETCODE】模拟面试-206. Reverse Linked List
- Eslint检测出的问题如何自动修复
- 【LEETCODE】模拟面试-215. Kth Largest Element in an Array
- Docker系列教程15-Docker容器网络
- 数据挖掘
- Docker系列教程14-Docker数据持久化
- Docker 学习系列二之基本管理
- Docker系列教程13-Docker可视化管理工具
- Ubuntu 16.04 安装VNC
- 使用Feign实现Form表单提交
- Ubuntu 16.04 Install OpenCV
- Spring Cloud各组件调优参数
- 手把手教你设置 IntelliJ IDEA 的彩色代码主题
- MySQL 教程
- MySQL 安装
- MySQL 管理与配置
- MySQL PHP 语法
- MySQL 连接
- MySQL 创建数据库
- MySQL 删除数据库
- MySQL 选择数据库
- MySQL 数据类型
- MySQL 创建数据表
- MySQL 删除数据表
- MySQL 插入数据
- MySQL 查询数据
- MySQL where 子句
- MySQL UPDATE 查询
- MySQL DELETE 语句
- MySQL LIKE 子句
- mysql order by
- Mysql Join的使用
- MySQL NULL 值处理
- MySQL 正则表达式
- MySQL 事务
- MySQL ALTER命令
- MySQL 索引
- MySQL 临时表
- MySQL 复制表
- 查看MySQL 元数据
- MySQL 序列 AUTO_INCREMENT
- MySQL 处理重复数据
- MySQL 及 SQL 注入
- MySQL 导出数据
- MySQL 导入数据
- MYSQL 函数大全
- MySQL Group By 实例讲解
- MySQL Max()函数实例讲解
- mysql count函数实例
- MYSQL UNION和UNION ALL实例
- MySQL IN 用法
- MySQL between and 实例讲解