type
status
date
slug
summary
tags
category
titleIcon
password
icon
insider


unsigned类型运算后要求仍为unsigned



数字类型
金额INT优于DECIMAL(分位制),且定长效率好
DECIMAL(小数点前位数,小数点后位数)
auto_increment主键自增,避免不够用(流水/日志表),优先bigint,8.0前自增值不持久化,重启可能回溯
撞上限重复
变长字段,容易造成碎片,需要进行空间碎片整理
小数点可以前端展示


状态枚举;时间日期;金融货币;
1.MD5十六进制
select hex('a0b1');
select unhex(61306231);
2.ip地址256进制
select inet_aton('192.168.0.1');
select inet_ntoa(3232235521);
3.日期
bigint
On 32-bit platforms, the maximum useful value forunix_timestamp
is 2147483647.999999, which returns'2038-01-19 03:14:07.999999'
UTC. On 64-bit platforms, the effective maximum is 32536771199.999999, which returns'3001-01-18 23:59:59.999999'
UTC. Regardless of platform or version, a greater value forunix_timestamp
than the effective maximum returns0
.
Date and Time Type Storage RequirementsForTIME
,DATETIME
, andTIMESTAMP
columns, the storage required for tables created before MySQL 5.6.4 differs from tables created from 5.6.4 on. This is due to a change in 5.6.4 that permits these types to have a fractional part, which requires from 0 to 3 bytes.
Data Type Storage Required Before MySQL 5.6.4 Storage Required as of MySQL 5.6.4 1 byte 1 byte 3 bytes 3 bytes 3 bytes 3 bytes + fractional seconds storage 8 bytes 5 bytes + fractional seconds storage 4 bytes 4 bytes + fractional seconds storageAs of MySQL 5.6.4, storage forYEAR
andDATE
remains unchanged. However,TIME
,DATETIME
, andTIMESTAMP
are represented differently.DATETIME
is packed more efficiently, requiring 5 rather than 8 bytes for the nonfractional part, and all three parts have a fractional part that requires from 0 to 3 bytes, depending on the fractional seconds precision of stored values.
Fractional Seconds Precision Storage Required 0 0 bytes 1, 2 1 byte 3, 4 2 bytes 5, 6 3 bytesFor example,TIME(0)
,TIME(2)
,TIME(4)
, andTIME(6)
use 3, 4, 5, and 6 bytes, respectively.TIME
andTIME(0)
are equivalent and require the same storage.For details about internal representation of temporal values, see MySQL Internals: Important Algorithms and Structures.
datetime 5位
from_unixtime 只接受到32536771199.999999(35位2进制)的数据转换
Java Instant转换
日期八股

字符串排序collation
字符串类型:COLLATION

CHAR(N)保存定长,N为0-255字符
VARCHAR(N)变长,N为0-65535
TEXT|BLOB 最大4GB
BLOB无字符集属性,二进制存储
VARCHAR通常足够 定义字符外还需要字符集 不同字符集编码 二进制数据不同
gbk微软windows utf8mb4(4应对emoji与部分汉字)
通常utf8mb4
更改服务器默认字符集配置(8.0前latin1 8.0后utf8mb4)

gbk最大2字节
同字符不同字符集的最大字节数不同
对InnoDB,如果定长达到或超过768字节(只会对utf8mb4才可能满足条件)char会变为变长存储
参考MySQL文档:
InnoDB
encodes fixed-length fields greater than or equal to 768 bytes in length as variable-length fields, which can be stored off-page. For example, aCHAR
(255)
column can exceed 768 bytes if the maximum byte length of the character set is greater than 3, as it is withutf8mb4
.


bin→binary二进制比较
ci → case insensitive不区分大小写
ai → accent insensitive不区分音标
默认大小写不敏感
一般不需要设置敏感
对新增的修改


对新增的与现有的字段修改

教程里对枚举或有限状态(如性别)不推荐int(脏数据与表达不清)
但一般来说,可以数据库层进行注释,在业务层一般只用枚举,不管读写都是,脏数据不大会发生,个人觉得影响不大
8.0开始的check约束


MD5加密不可逆但值固定,可以查表,需要加盐(盐值不同结果不同)

注册时产生不同盐值(可以再加上用户注册日期合并一个盐值)并存在数据库中
加密算法可用代号v1 v2 v3
value加密后字符串

可升级加密算法版本对密码升级进一步防范


第一条未必成立
第五条未必需要



底层多字符字符集 varchar char都是变长

在默认utf8mb4下两个实现一样











enum非sql标准,mysql独有的字符串类型
8.0.16起提供约束功能









可动态盐再合并用户注册日期


密码相同 12345678 存储内容不同
就算拿到密码 加密算法
可以对存储的密码进行升级防范





图片路径 base64
日期类型








daylight saving time










调用操作系统时区 系统调用 上锁 并发问题 ???







订单超时处理
主从数据核对




非结构存储




存储登录信息




JSON表达式
MySQL函数索引索引JSON字段
虚拟列







8.0.17

JSON数组上创建索引









表结构设计-忘记范式






告警 日志 表





36 → 16













订单 后6位相同








表压缩











compress压缩使用性能不敏感业务 日志表 告警表 监控表

存在压缩解压两个页,压缩写入,解压读取(不需要每次都解压)








性能抖动





SQL or NoSQL


















可以结合sql进行复杂的查询,比如结合窗口函数










索引




二叉树 哈希索引 红黑树 skiplist 海量基于磁盘存储数据效率

树矮 插入效率高 排序比较定位快


叶子结点内排序好了,只需二分查找



innoDB 页大小16K




如果查询页缓存在内存缓冲池可以更快



有序:如自增id 时间列 索引插入较快
无序:还存在磁盘随机读写性能不如顺序写影响 比如用户昵称


自增 UUID_TO_BIN 排序UUID




查看未被使用过的b+树索引

数据库运行时间长 索引创建时间久 出现在表格中 可以考虑废弃
MySQL 8.0 在删除索引前可以考虑设置索引对优化器不可见,观察是否对业务有影响



索引组织表
b+树索引基本概念 与 简单管理
mysql innodb存储引擎索引结构

数据存储有堆表(无序存放,数据排序完全依赖于索引)
数据 索引 分开存储 索引是排序后的数据 堆表中的是无序的
索引叶子结点存放了数据在堆表中的地址
当堆表中的数据变化且改变位置,所有索引中的地址都要更新 影响性能

索引组织表 两种方式



innoDB数据是根据主键索引排序存储的,除了主键索引外,其余索引都是二级索引/非聚集索引
二级索引也是b+树索引

不同于主键索引的是叶子结点存放索引主键值


二级索引通过主键索引进行再次查询的设计:如果记录发生修改,其他索引不用维护,除非主键变了
索引组织表在大量变更情况下相比堆表优势明显 大部分情况下都不需要维护二级索引



唯一索引也是二级索引







限制昵称更改频率 提高性能


插入比较顺序 但存在频繁更新操作 对应字段更新导致二级索引修改
因为二级索引需要回表查询,所以设计表结构时让主键值尽可能紧凑,就是为了提高二级索引的性能
16字节顺序UUID

5.7开始







但这时有两份索引 影响性能

虚拟列 由后续表达式计算得到 本身不占据任何存储空间
idx_cellphone实质为函数索引
这样好处是写sql时可以直接使用虚拟列 而不用写冗长的函数

爬虫业务中虚拟列筛选出想要的数据,在虚拟列上创建函数索引对想要的数据快速访问搜索


组合索引


写b=?前也一样

不适用以下sql (a,b)排序不能推出(b,a)排序

可以使用组合索引

不可


根据某个列查询,按照时间方式逆序展示
微博、淘宝订单



额外排序 extra:using filesort




二级索引叶子节点索引键值 主键值

如果查询字段在二级索引的叶子结点中可以直接返回结果避免回表
通过组合索引避免回表的优化→索引覆盖







根据rows估计回表次数






索引出错 CBO


创建索引但使用了全表扫描,问题在索引对应的数据上

优化器选择索引基于成本 CBO cost-based optimizer 分析所有执行计划


CPU:索引键值、记录值比较、结果集排序
IO:8.0可以区分表是否在内存中计算在内存和不在的开销






查询范围不同,索引选择也可能不同


二级索引回表,全表扫描成本低于二级索引



B+树索引需要建立在高选择性的字段上
如订单id 日期等
较少建立在对候选值较少的低选择性字段如性别上
但电商中需要对order_status低选择性字段建立索引

这一字段存在数据倾斜(大部分已完成) 且只查询少量数据

可以对其创建索引

mysql不知道不同值分布,当作平均分布
所以以为全表扫描快于二级索引回表
但由于数据倾斜,事实上会更快

8.0创建直方图 让优化器知道数据分布 从而更好地选择执行计划

创建完后mysql会获得数据分布情况




Join
除了单表设计优化还有多表join与子查询

关联表的数量,查询数据量的多少 OLTP一般左 OLAP右(直接全表效率高)

Nested Loop Join通过索引进行匹配 表R驱动表 通过Where过滤的数据会在S中一一查询
如果驱动表数据量较大 该算法比较高效


INNER JOIN需要查询数量少的表为驱动表

通过索引的效率默认一致,算法会要求驱动表的数量尽可能少







8.0开始支持对OLAP关键的Hash Join算法


海量并发 响应即时

OLTP 若join带有where过滤条件 并且根据主键索引过滤 驱动表只有少量数据 开销小
优化器自行拆分 需要确保索引都已创建


确保使用正确的索引与索引覆盖就可以




12 OLAP
子查询






看执行计划






- 作者:CamelliaV
- 链接:https://camelliav.netlify.app/article/mysql-1
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
相关文章