本规范以阿里数据库设计规范为基础,结合实际开发场景制定,涵盖命名、设计、类型、索引、SQL五大核心维度,明确各环节的强制、推荐及参考级要求,旨在保障数据库设计的规范性、一致性、高性能及可维护性。

命名规范篇

命名需遵循“见名知意、简洁统一、兼容跨平台”原则,所有命名均使用小写字母、数字及下划线,禁止使用保留字,且需控制长度以确保兼容性。

基础命名规则(强制)

  • 是与否字段命名:必须使用“is_xxx”格式,数据类型为unsigned tinyint(1表示是,0表示否)。非负数字段均需指定unsigned。正例:is_deleted(1-删除,0-未删除);反例:delete_flag、isDelete。

  • 表名/字段名规则:仅使用小写字母或数字,禁止数字开头,禁止“_数字_”格式;长度控制在32个字符内,不同单词用下划线分割。说明:MySQL在Windows下不区分大小写,Linux下区分,统一小写可避免环境问题。正例:health_user、rdc_config、level3_name;反例:HealthUser、rdcConfig、level_3_name。

  • 表名单复数:表名使用单数名词,仅表示实体内容而非数量,与DO类名保持一致。正例:user、order;反例:users、orders。

  • 保留字禁用:库名、表名、列名禁止使用MySQL保留字(如desc、range、match、delayed等),建表或新增字段时需规避,避免SQL审计告警。

  • 索引命名:主键索引名“pk_字段名”,唯一索引名“uk_字段名”,普通索引名“idx_字段名”。正例:pk_id、uk_user_phone、idx_create_time。

  • 库名规则:长度≤30字符,仅含英文、数字、下划线,以英文字母开头且全小写;格式为“业务系统名称_子系统名”。正例:health_user、trade_payment。

  • 表必备字段:必须包含id(主键)、is_delete(逻辑删除)、gmt_create(创建时间)、gmt_modified(更新时间)。id类型为unsigned bigint,单表自增步长1,多机房可使用全局id或分机房起始数错开(步长≥机房数);gmt_create与gmt_modified为datetime类型。

  • 命名全称要求:所有命名使用全名,有默认约定除外;超过30字符可使用易懂缩写(如description→desc、information→info、address→addr)。

推荐命名规则

  • 表名前缀:表名建议为“业务名称_表作用”,且与模块强相关,同一模块使用统一前缀。正例:health_user(健康业务用户表)、crm_fund_item(客户关系业务资金项表)。

  • 库名与应用对应:库名尽量与应用名称一致,便于关联管理。正例:应用名health对应库名health。

  • 注释更新:修改字段含义或状态追加时,需及时更新字段注释,确保可读性。

  • 时间字段命名:时间字段以“gmt_”开头,后跟动词过去式,不添加“time”后缀。正例:gmt_create、gmt_modified;反例:create_time、update_time。

设计规范篇

设计需兼顾性能、一致性与可扩展性,明确库、表、字段的创建规则及优化方向,避免设计缺陷导致的后期维护难题。

库设计

  • 字符集指定(强制):创建数据库时必须显式指定字符集,仅允许utf8或utf8mb4。SQL示例:CREATE DATABASE crm_fund DEFAULT CHARACTER SET 'utf8';

  • 权限最小原则(建议):程序连接数据库账号遵循权限最小原则,仅允许单库访问,禁止跨库;原则上无drop权限。

  • 临时库与备份库命名:临时库以“tmp_”为前缀、日期为后缀;备份库以“bak_”为前缀、日期为后缀。正例:tmp_user_20251128、bak_order_20251127。

表与字段设计

  • 表创建基础规则(强制):创建表时必须显式指定字符集(utf8或utf8mb4)和存储引擎,无特殊需求时引擎为InnoDB。

  • 字段冗余原则(强制):允许适当冗余提升查询性能,但需保证数据一致,冗余字段需满足:非频繁修改、非超长varchar/text字段、冗余字段≤总字段数20%。正例:商品表冗余类目名称(类目名称使用频繁、长度短、修改少)。

  • 分库分表阈值(推荐):单表行数超过500万行或容量超过2GB时,推荐分库分表;预计2年内达不到该级别则不提前拆分。

  • 主键规则(推荐):id必须为主键且保持增长趋势,小型系统可使用MySQL自增主键,大型系统或分库分表时使用全局ID或唯一标识字段。

  • id类型(强制):id类型无特殊要求时必须使用bigint unsigned,禁止使用int,即使当前数据量小。说明:便于对接外部系统、规避废数据影响、适配未来分库分表(自动生成ID多为8字节)。

  • 字段非空与默认值(推荐):字段尽量设置为NOT NULL并提供默认值,字符型默认空字符串'',数值型默认0,逻辑型默认0(false)。

  • 注释要求(推荐):每个字段和表必须提供清晰注释,说明含义、用途及特殊规则。

  • 时间格式(推荐):所有时间字段统一使用“yyyy-MM-dd HH:mm:ss”格式存储。

  • 更新时间维护(强制):更新表记录时,必须同步更新gmt_modified字段为当前时间。

  • 字段数量限制(强制):单表字段建议不超过50个,硬性要求不超过100个。

  • 敏感数据存储(强制):禁止存储明文密码,需加密处理;禁止存储图片、文件等大二进制数据,应存储于文件服务器,数据库仅保留文件地址。

  • 时间字段必备(建议):表必须包含gmt_create(创建时间)和gmt_modified(更新时间),便于问题排查。

  • 关联字段一致性(建议):存储相同数据的列名和列类型必须一致,避免隐式转换导致索引失效。正例:用户表user_id为bigint unsigned,订单表user_id也需为bigint unsigned。

  • 预留字段(建议):评估预留1-3个字段,避免后期表扩容变更的繁琐操作。

  • 字段命名简洁性(强制):字段命名使用表达实际含义的英文单词或缩写,避免冗余。正例:公司ID用corp_id而非corporation_id。

类型规范篇

根据数据特性选择合适的字段类型,兼顾存储效率、精度与查询性能,避免类型不当导致的性能问题或数据异常。

  • 状态字段类型(强制):状态字段(0-255)使用TINYINT UNSIGNED,禁止使用枚举类型;注释需明确各状态含义及是否支持多选。

  • 布尔类型映射(强制):表示boolean类型的字段使用TINYINT(1)(MySQL无原生boolean类型,此类型可自动生成DO的boolean字段,如is_delete);其他场景使用TINYINT(4)。说明:TINYINT括号内为显示宽度,仅zerofill时有效,无特殊需求可不指定括号内数值。

  • 非负字段标识(强制):非负数字类型字段必须添加UNSIGNED,如INT UNSIGNED可存储IPv4地址。

  • 时间类型选择(强制):时间字段使用日期时间类型而非字符串,日期用DATE,年份用YEAR,日期时间用DATETIME。反例:用VARCHAR存储“2025-11-28”。

  • 字符串类型规范(强制):VARCHAR(N)中N表示字符个数,需尽量减小N值(如code VARCHAR(32)、name VARCHAR(32)、memo VARCHAR(512));Blob和Text类型因易产生碎片需避免使用,若必须使用需单独拆表。

  • 精确浮点类型(强制):钱币等需精确计算的字段使用DECIMAL类型,禁止使用float和double(存在精度损失);若数据范围超DECIMAL,可拆分为整数和小数分开存储。

  • 类型选择原则(强制):数值字段增长上限不大时,不使用BIGINT;新建表时字段必须填写描述,枚举值需明确所有含义。

  • 存储效率优化(建议):优先选择满足存储需求的最小数据类型,如存储0-100的数值用TINYINT而非INT;合理选择定长与非定长类型,平衡精度与存储成本。

  • 字符长度适配(参考):根据实际业务场景选择合适的字符存储长度,节约表空间与索引存储,提升检索速度。

索引规范篇

索引设计需平衡查询性能与更新成本,明确索引创建、使用及优化的规则,避免无效索引或过度索引。

  • 唯一索引必备(强制):业务上具有唯一特性的字段(含多字段组合)必须创建唯一索引,避免脏数据产生,提升查询效率。

  • 关联查询限制(强制):禁止超过三个表的JOIN操作;JOIN字段数据类型必须一致,且被关联字段需有索引。

  •  varchar索引长度(强制):在varchar字段上建立索引时必须指定长度,根据文本区分度确定(通常长度20区分度达90%以上),可通过“count(distinct left(列名, 索引长度))/count(*)”计算区分度。

  • 模糊查询限制(强制):页面搜索严禁左模糊或全模糊(%打头),此类查询无法使用索引,需通过搜索引擎解决。

  • 索引重建规则(强制):重建索引时必须先创建新索引再删除旧索引(尤其是唯一索引),避免索引缺失导致的数据完整性问题和慢查询。

  • 索引数量控制(参考):单表索引数不超过6个,避免过度索引导致更新性能下降;避免“宁滥勿缺”(一个查询建一个索引)或“宁缺勿滥”(拒绝必要索引)的极端认知,不抵制唯一索引。

  • 排序与索引适配(推荐):order by场景需利用索引有序性,将order by字段作为组合索引的最后一列,避免file_sort。正例:where a=? and b=? order by c,索引为a_b_c;反例:where a>10 order by b,索引a_b无法排序。

  • 覆盖索引优先(推荐):利用覆盖索引避免回表查询,explain结果中extra列显示“using index”即为覆盖索引。正例:查询用户手机号时,建立idx_user_phone(phone)索引,避免查询主键后回表取手机号。

  • 超多分页优化(推荐):通过延迟关联或子查询优化超多分页场景,先定位id段再关联查询。正例:SELECT a.* FROM 表1 a, (select id from 表1 where 条件 LIMIT 100000,20 ) b where a.id=b.id。

  • 性能级别目标(推荐):SQL性能优化目标至少达到range级别,优先ref级别,最佳consts级别。说明:consts(主键/唯一索引匹配,优化阶段读取数据)、ref(普通索引匹配)、range(索引范围检索)。

  • 联合索引顺序(推荐):联合索引列顺序遵循“区分度高→字段长度小→使用频繁”原则;等号条件字段前置(如where a>? and b=?,索引需将b放前面)。正例:where a=? and b=?,a区分度极高时,单建idx_a即可。

  • 索引失效规避(推荐):防止字段类型不同导致的隐式转换(如字符串与数字比较),避免索引失效;索引选择唯一性强、数据类型短的字段。

  • 索引列选择(推荐):索引列优先选择WHERE从句中的过滤列、ORDER BY/GROUP BY/DISTINCT中的字段、多表JOIN的关联列;优先建立联合索引而非多个单列索引。

索引使用总结:① 控制索引数量,避免重复索引,尽量缩短索引长度;② 仅为常用查询条件建索引,过滤性低的列不建索引;③ 唯一记录建唯一索引,频繁更新的列不建索引;④ 避免对索引列运算,合理设计联合索引顺序(过滤性高的列前置);⑤ order by字段建索引避免filesort,组合索引不支持反向排序;⑥ <>、!=等非等值操作符可能导致索引失效。

SQL规范篇

SQL编写需遵循性能优化、安全可靠的原则,明确各类SQL操作的禁忌与最佳实践,避免慢查询、数据异常等问题。

基础查询规范(强制)

  • count函数使用:使用count(*)统计行数,禁止用count(列名)替代;count(*)兼容跨数据库,统计所有行(含NULL值),count(列名)不统计NULL值。

  • distinct与sum注意事项:count(distinct col)统计非NULL不重复行数;count(distinct col1, col2)中若一列全为NULL,返回0;sum(col)在列全为NULL时返回NULL,需用“IF(ISNULL(SUM(g)),0,SUM(g))”规避NPE。

  • NULL判断方式:使用ISNULL()判断NULL值,禁止直接比较(NULL与任何值比较结果为NULL)。

  • 分页查询优化:分页逻辑中若count为0,直接返回,避免执行后续分页语句;能确定返回一条结果时,加LIMIT 1。

  • 外键与级联禁用:禁止使用外键与级联,所有外键逻辑在应用层实现。说明:外键与级联适用于单机低并发,不适合分布式高并发,易引发更新风暴。

  • 存储过程禁用:禁止使用存储过程,其难以调试扩展且无移植性。

  • 数据订正规则:删除/修改记录前需先查询并记录主键,以主键为条件执行操作,避免误删。正例:更新is_delete时,先select id where 业务条件,再update ... where id in (...)。

  • 大表操作限制:业务系统禁止大表(500万行以上)JOIN,50万行以上表禁止聚合运算(count、sum等)及GROUP BY;大表查询仅支持单表,需用高区分度索引,返回行数≤100条。

  • 批量操作限制:批量写(UPDATE、DELETE、INSERT)需分批执行并加LIMIT;INSERT ... VALUES(...)中值的数量不超过5000个,避免主从同步延迟。

  • 索引列运算禁用:WHERE条件中禁止对列使用函数(如where DATE(create_time)='2025-11-28'),会导致索引失效(除非有函数索引)。

  • 多表更新禁用:禁止单条语句同时更新多个表。

  • 事务控制:杜绝大事务,事务内SQL不超过5条,避免锁持有时间过长;只读查询不开启事务;事务内更新语句尽量基于主键或唯一索引,避免间隙锁。

  • 子查询优化:少用子查询,改用JOIN(子查询含GROUP BY、DISTINCT等易产生临时表)。

  • DML条件要求:DML语句必须有WHERE条件且使用索引查找,禁止无条件更新/删除。

  • in条件限制:in操作需控制元素数量≤1000个;MyBatis使用in时需判空,避免空集合导致全表扫描。

推荐SQL实践

  • 批量插入优化:多条INSERT使用批量插入(INSERT INTO table VALUES(),(),()...),提升效率。

  • 隐式转换规避:避免SQL中的隐式转换,如非字符类型字段不使用字符串值比较(where id='1'中id为bigint)。

  • INSERT字段指定:INSERT语句需指定具体字段名称,禁止写为INSERT INTO t1 VALUES(...),避免字段顺序变更导致错误。

  • UNION优化:优先使用UNION ALL替代UNION(UNION需去重,消耗资源),UNION子句个数≤5个。

  • 排序优化:减少ORDER BY使用,可将排序转移至应用端;必须排序时确保使用索引。

  • 高并发规避:避免使用insert into ... on duplicate key update...,高并发下易导致主从不一致。

  • 多表JOIN优化:多表JOIN时,区分度大的字段放前面,优先考虑覆盖索引,避免冗余索引,综合评估数据密度与查询更新比例。

SQL性能总结:① 快速缩小结果集的WHERE条件前置,含恒量条件(如where 1=1);② 避免GROUP BY、DISTINCT、联表及子查询;③ 索引列使用>、≥、=、<、≤、IF NULL、BETWEEN可命中索引,LIKE 'abc%'可命中,'%abc%'不可;④ 避免使用SELECT *,仅取需要字段,提升覆盖索引使用率;⑤ 连续数值用BETWEEN替代IN,减少WHERE从句中CASE条件;⑥ LIMIT越大效率越低,需优化超多分页场景。

建表语句示例: