Skip to main content

注意事项



数字类型
不推荐使用整型类型的属性 Unsigned,若非要使用,参数 sql_mode 务必额外添加上选项 NO_UNSIGNED_SUBTRACTION;

自增整型类型做主键,务必使用类型 BIGINT,而非 INT,后期表结构调整代价巨大;

MySQL 8.0 版本前,自增整型会有回溯问题,做业务开发的你一定要了解这个问题;

当达到自增整型类型的上限值时,再次自增插入,MySQL 数据库会报重复错误;

不要再使用浮点类型 Float、Double,MySQL 后续版本将不再支持上述两种类型;

账户余额字段,设计是用整型类型,而不是 DECIMAL 类型,这样性能更好,存储更紧凑。






排序规则以 _ci 结尾,表示不区分大小写(Case Insentive),_cs 表示大小写敏感,_bin 表示通过存储字符的二进制进行比较

错误修改字符集
ALTER TABLE emoji_test CHARSET utf8mb4;
正确
ALTER TABLE emoji_test CONVERT TO CHARSET utf8mb4;

限制值
Create Table: CREATE TABLE `User` (

`id` bigint NOT NULL AUTO_INCREMENT,

`sex` char(1) COLLATE utf8mb4_general_ci DEFAULT NULL,

PRIMARY KEY (`id`),

CONSTRAINT `user_chk_1` CHECK (((`sex` = _utf8mb4'M') or (`sex` = _utf8mb4'F')))

) ENGINE=InnoDB



密码
$salt$cryption_algorithm$value
$salt:表示动态盐,每次用户注册时业务产生不同的盐值,并存储在数据库中。若做得再精细一点,可以动态盐值 + 用户注册日期合并为一个更为动态的盐值。
$cryption_algorithm:表示加密的算法,如 v1 表示 MD5 加密算法,v2 表示 AES256 加密算法,v3 表示 AES512 加密算法等。
$value:表示加密后的字符串。

日期
日期类型通常就是使用 DATETIME 和 TIMESTAMP 两种类型,然而由于类型 TIMESTAMP 存在性能问题,建议你还是尽可能使用类型 DATETIME。
INT 类型就是直接存储 ‘1970-01-01 00:00:00’ 到现在的毫秒数,本质和 TIMESTAMP 一样,因此用 INT 不如直接使用 TIMESTAMP。

CREATE TABLE User (

id BIGINT NOT NULL AUTO_INCREMENT,

name VARCHAR(255) NOT NULL,

sex CHAR(1) NOT NULL,

password VARCHAR(1024) NOT NULL,

money INT NOT NULL DEFAULT 0,

register_date DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),

last_modify_date DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),

CHECK (sex = 'M' OR sex = 'F'),

PRIMARY KEY(id)

);
通过字段 last_modify_date 定义的 ON UPDATE CURRENT_TIMESTAMP(6),那么每次这条记录,则都会自动更新 last_modify_date 为当前时间。

我总结一下今天的重点内容:

MySQL 5.6 版本开始 DATETIME 和 TIMESTAMP 精度支持到毫秒;
DATETIME 占用 8 个字节,TIMESTAMP 占用 4 个字节,DATETIME(6) 依然占用 8 个字节,TIMESTAMP(6) 占用 7 个字节;
TIMESTAMP 日期存储的上限为 2038-01-19 03:14:07,业务用 TIMESTAMP 存在风险;
使用 TIMESTAMP 必须显式地设置时区,不要使用默认系统时区,否则存在性能问题,推荐在配置文件中设置参数 time_zone = ‘+08:00’;
推荐日期类型使用 DATETIME,而不是 TIMESTAMP 和 INT 类型;
表结构设计时,每个核心业务表,推荐设计一个 last_modify_date 的字段,用以记录每条记录的最后修改时间。


json

SELECT

userId,

JSON_UNQUOTE(JSON_EXTRACT(loginInfo,"$.cellphone")) cellphone,

JSON_UNQUOTE(JSON_EXTRACT(loginInfo,"$.wxchat")) wxchat

FROM UserLogin;



SELECT

userId,

loginInfo->>"$.cellphone" cellphone,

loginInfo->>"$.wxchat" wxchat

FROM UserLogin;

创建索引
ALTER TABLE UserLogin ADD COLUMN cellphone VARCHAR(255) AS (loginInfo->>"$.cellphone");

ALTER TABLE UserLogin ADD UNIQUE INDEX idx_cellphone(cellphone);

上述 SQL 首先创建了一个虚拟列 cellphone,这个列是由函数 loginInfo->>“$.cellphone” 计算得到的。然后在这个虚拟列上创建一个唯一索引 idx_cellphone。这时再通过虚拟列 cellphone 进行查询,就可以看到优化器会使用到新创建的 idx_cellphone 索引:

同上
CREATE TABLE UserLogin (

userId BIGINT,

loginInfo JSON,

cellphone VARCHAR(255) AS (loginInfo->>"$.cellphone"),

PRIMARY KEY(userId),

UNIQUE KEY uk_idx_cellphone(cellphone)

);

json 数组 索引

ALTER TABLE UserTag
ADD INDEX idx_user_tags ((cast((userTags->"$") as unsigned array)));

查询
EXPLAIN SELECT * FROM UserTag
WHERE JSON_OVERLAPS(userTags->"$", '[2,3,10]')\G