- 【强制】表名、字段名必须使用小写字母或数字,禁止出现数字开头,禁止两个下划线中间只出现数字。数据库字段名的修改代价很大,所以字段名称需要慎重考虑。说明:
MySQL
在Windows
下不区分大小写,但在Linux
下默认是区分大小写。因此,数据库名、表名、字段名,都不允许出现任何大写字母,避免节外生枝。正例:aliyun_admin
,rdc_config
,level3_name
反例:AliyunAdmin
,rdcConfig
,level_3_name
- 【强制】表名字段名不使用英文与拼音的复合表达式,符合表达习惯。禁用保留字,如
desc
、date
、range、match、delayed
等,请参考MySQL官方保留字。 - 【强制】主键索引名为
pk_
字段名;唯一索引名为uk_
字段名;普通索引名则为idx_
字段名。 说明:pk_
即primary key
;uk_
即unique key
;idx_
即index
的简称。
-
【强制】不得使用外键与级联,一切外键概念必须在应用层解决。 说明:以学生和成绩的关系为例,学生表中的
student_id
是主键,那么成绩表中的student_id
则为外键。如果更新学生表中的student_id
,同时触发成绩表中的student_id
更新,即为级联更新。外键与级联更新适用于单机低并发,不适合分布式、高并发集群;级联更新是强阻塞,存在数据库更新风暴的风险;外键影响数据库的插入速度。 -
【强制】所有的字符存储与表示,均以
utf-8
编码,注意字符统计函数的区别。 -
【强制】如果存储的字符串长度几乎相等,使用
char
定长字符串类型。 -
【强制】
varchar
是可变长字符串,不预先分配存储空间,长度不要超过 2000,如果存储长度大于此值,定义字段类型为text
,独立出来一张表,用主键来对应,避免影响其它字段索引效率。 -
【推荐】表必备三字段:
id, createon, updateon
。 说明:其中id必为主键,类型为bigint unsigned
、单表时自增、步长为1。createon, updateon
的类型均为datetime
类型。 -
【推荐】所有字段都应该有默认值,不应该存在值为
NULL
的列,NULL
值在统计中会造成很多麻烦。 -
【推荐】字段允许适当冗余,以提高查询性能,但必须考虑数据一致。冗余字段应遵循:
1)不是频繁修改的字段。
2)不是
varchar
超长字段,更不能是text
字段。 正例:商品类目名称使用频率高,字段长度短,名称基本一成不变,可在相关联的表中冗余存储类目名称,避免关联查询。 -
【推荐】单表行数超过 500 万行或者单表容量超过 2GB,才推荐进行分库分表。 说明:如果预计三年后的数据量根本达不到这个级别,请不要在创建表时就分库分表。
-
【强制】勿认为一个查询就需要建一个索引,也不要胡乱认为索引会消耗空间、严重拖慢更新和新增速度,而是应该业务需求考虑索引的必要程度。
-
【强制】对于有限的几个值的列不需要建索引。
-
【强制】经常出现在
where
条件和order by
子句中的列一定要建立索引。 -
【强制】业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引。
说明:不要以为唯一索引影响了
insert
速度,这个速度损耗可以忽略,但提高查找速度是明显的;另外,即使在应用层做了非常完善的校验控制,只要没有唯一索引,根据墨菲定律,必然有脏数据产生。 -
【强制】在
varchar
字段上建立索引时,必须指定索引长度,一般来说 8 位即可,没必要对全字段建立索引,根据实际文本区分度决定索引长度即可。 -
【推荐】
SQL
性能优化的目标:至少要达到
range
级别,要求是
ref
级别,如果可以是
consts
最好。
说明:
1)
consts
单表中最多只有一个匹配行(主键或者唯一索引),在优化阶段即可读取到数据。2)
ref
指的是使用普通的索引(normal index
)。3)
range
对索引进行范围检索。 反例:explain
表的结果,type=index
,索引物理文件全扫描,速度非常慢,这个index
级别比较range
还低,与全表扫描是小巫见大巫。
- 【强制】不要使用
count(列名)
或count(常量)
来替代count(*)
,count(*)
是SQL92
定义的标准统计行数的语法,跟数据库无关,跟NULL
和非NULL
无关。 说明:count(*)
会统计值为NULL
的行,而count(列名)
不会统计此列为NULL
值的行。 - 【强制】
order by
排序的时候如果是根据创建时间来排序,不要使用createon
列,直接用order by id
或者order by id desc
。说明:通过主键来排序大幅提高性能。 - 【强制】 在代码中写分页查询逻辑时,若
count
为0应直接返回,避免执行后面的分页语句。 - 【强制】
where
条件中如果字段是字符类型,代码中的条件值必须加上引号,避免索引失效。 - 【强制】在表查询中,一律不要使用 作为查询的字段列表,需要哪些字段必须明确写明。 说明:1)增加查询分析器解析成本;2)无用字段增加网络消耗,尤其是text类型的字段。
- 【强制】禁止使用存储过程,存储过程难以调试和扩展,更没有移植性。
- 【强制】 除临时表外程序中禁止使用
TRUNCATE TABLE
。说明:TRUNCATE TABLE
在功能上与不带WHERE
子句的DELETE
语句相同,极有可能造成事故。 - 【推荐】
in
操作能避免则避免,若实在避免不了,需要仔细评估in
后边的集合元素数量,控制在1000个之内。 - 【推荐】不要写一个大而全的数据更新接口。不管是不是自己的目标更新字段,都进行
update table set c1=value1,c2=value2,c3=value3;
这是不对的。执行SQL
时,不要更新无改动的字段,一是易出错;二是效率低;三是增加binlog
存储。 - 【推荐】利用延迟关联或者子查询优化超多分页场景。 说明:
MySQL
并不是跳过offset
行,而是取offset+N
行,然后返回放弃前offset
行,返回N
行,那当offset
特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过特定阈值的页数进行SQL
改写。 正例:先快速定位需要获取的id
段,然后再关联:SELECT a.* FROM 表1 a, (select id from 表1 where 条件 LIMIT 100000,20 ) b where a.id=b.id
- 【推荐】建组合索引的时候,区分度最高的在最左边。 正例:如果
where a=? and b=?
,如果a
列的几乎接近于唯一值,那么只需要单建idx_a
索引即可。 说明:存在非等号和等号混合时,在建索引时,请把等号条件的列前置。如:where c>? and d=?
那么即使c
的区分度更高,也必须把d放在索引的最前列,即索引idx_d_c
。 - 【推荐】超过三个表禁止
join
。需要join
的字段,数据类型必须绝对一致;多表关联查询时,保证被关联的字段需要有索引。 说明:即使双表join
也要注意表索引、SQL
性能。