【推荐】表的全名最好是遵循"业务名称_表的作用"。
【推荐】库名与应用名称尽量一致。
【强制】表名、字段名必须使用小写字母或数字,禁止出现数字开头,禁止两个下划线中间只出现数字。数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑。
【强制】表名不使用复数名词,尽量做到见名知意。
【强制】表必备三字段:gid, created_at, updated_at。
说明:其中gid 必为主键,类型为bigint unsigned或int unsigned、单表自增、步长为1。created_at的类型为datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,updated_at的类型为datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP。
【强制】禁用保留字,如desc、range、match、delayed等,请参考MySQL官方保留字。
【强制】小数类型为decimal,禁止使用float和double。
【强制】主键索引名为pk_字段名;唯一索引名为uk_字段名[_字段名];普通索引名则为idx_字段名[_字段名]。
【强制】外键约束不在数据库上创建,只表达一个逻辑的概念,由程序控制。
【强制】varchar是可变长字符串,不预先分配存储空间,长度不要超过5000,如果存储长度大于此值,定义字段类型为 text,独立出来一张表,用主键来对应,避免影响其它字段索引效率。
【推荐】如果修改字段含义或对字段表示的状态追加时 ,需要及时更新字段注释。
【推荐】字段允许适当冗余,以提高查询性能,但必须考虑数据一致。冗余字段应遵循:
不是频繁修改的字段
不是varchar超长字段,更不能是text字段
不是唯一索引的字段
【参考】合适的字符存储长度,不但节约数据库表空间、节约索引存储,更重要的是提升检索速度。
【参考】存日期使用DATE类型。
【参考】逻辑主键(自增主键)不用作业务主键,需另定义一个业务主键。
【参考】默认使用utf8mb4字符集,数据库排序规则使用utf8mb4_general_ci
二、索引
【强制】业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引。
【强制】超过三个表禁止join。需要join的字段,数据类型必须绝对一致;多表关联查询时,保证被关联的字段需要有索引。
【强制】在varchar字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据实际文本区分度决定索引长度即可。
【强制】页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决。
【推荐】建组合索引的时候,区分度最高的在最左边。
【推荐】防止因字段类型不同造成的隐式转换,导致索引失效。
【推荐】关联其它表的外键字段必须要创建索引。
【推荐】单张表的索引控制在5个以内,索引中的字段数不超过5个。
【推荐】如果有 order by 的场景,请注意利用索引的有序性。order by 最后的字段是组合 索引的一部分,并且放在索引组合顺序的最后,避免出现 file_sort 的情况,影响查询性能。
正例:where a=? and b=? order by c; 索引:a_b_c
反例:索引如果存在范围查询,那么索引有序性无法利用,如:WHERE a>10 ORDER BY b; 索引 a_b 无法排序。
【推荐】利用覆盖索引来进行查询操作,避免回表。
【强制】业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引。
【强制】超过三个表禁止join。需要join的字段,数据类型必须绝对一致;多表关联查询时,保证被关联的字段需要有索引。
【强制】在varchar字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据实际文本区分度决定索引长度即可。
【强制】页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决。
【推荐】建组合索引的时候,区分度最高的在最左边。
【推荐】防止因字段类型不同造成的隐式转换,导致索引失效。
【推荐】关联其它表的外键字段必须要创建索引。
【推荐】单张表的索引控制在5个以内,索引中的字段数不超过5个。
【推荐】如果有 order by 的场景,请注意利用索引的有序性。order by 最后的字段是组合 索引的一部分,并且放在索引组合顺序的最后,避免出现 file_sort 的情况,影响查询性能。
正例:where a=? and b=? order by c; 索引:a_b_c
反例:索引如果存在范围查询,那么索引有序性无法利用,如:WHERE a>10 ORDER BY b; 索引 a_b 无法排序。
【推荐】利用覆盖索引来进行查询操作,避免回表。
禁止使用select *, * 用所需字段代替
禁止使用select for update
禁止在where条件的列名上使用函数
禁止使用子查询
update/delete只能单表操作,不允许多表关联,不允许子查询,且一定要带where条件
insert语句要显式指定插入的列名,且不允许使用insert...select的形式
禁止使用存储过程、存储函数、触发器、视图
避免使用or,用union代替
尽量不要在数据库里做运算
尽量不要做%前缀模糊查询,如like '%name'
不要使用大偏移量的limit分页
批量insert语句最好采用bulk insert的方法,如insert into table(***) values(***),(***),每个批次以执行时间小于1秒为原则
update/delete尽量根据主键进行操作
尽量减少count()的使用,尤其是用来频繁获取全表记录数
使用group by时,如无排序的需求,建议加order by null
join中使用的关联字段使用统一的数据类型
尽量不要在查询语句中指定强制索引force index
需要格外注意的场景
没有where条件的sql
使用count(*)
使用like
使用text字段
多语句事务
use test;
CREATE TABLE `test`.`user` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(32) NOT NULL DEFAULT '0' COMMENT '账号',
`password` varchar(32) NOT NULL COMMENT '密码',
`email` varchar(32) NOT NULL COMMENT '邮箱',
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`deleted_at` datetime DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `test`.`threads` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`user_id` varchar(32) NOT NULL DEFAULT '0' COMMENT '用户ID',
`topic` text COMMENT '帖子',
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`deleted_at` datetime DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `test`.`posts` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`user_id` varchar(32) NOT NULL DEFAULT '0' COMMENT '用户ID',
`threads_id` varchar(32) NOT NULL DEFAULT '0' COMMENT '帖子ID',
`body` text COMMENT '密码',
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`deleted_at` datetime DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
网友评论