MySQL数据库开发设计规范总结

MySQL数据库开发设计规范总结

概述

从数据库的设计原则、命名规范等方面论述数据库设计的规范思想及命名规则。参照以下原则进行数据库设计:

  1. 方便业务功能实现、业务功能扩展
  2. 方便设计开发、增强系统的稳定性和可维护性
  3. 保证数据完整性和准确性
  4. 提高数据存储效率,在满足业务需求的前提下,使时间开销和空间开销达到优化平衡

MySQL数据库设计规范

设计规范-库

1.【强制】库的名称必须控制在30个字符以内,只能使用英文字母、数字和下划线,建议以英文字母开头。

2.【强制】库名中英文一律小写,不同单词采用下划线分割。须见名知意。

3.【强制】库的名称格式:业务系统名称_子系统名。

4.【强制】库名禁止使用关键字(如type,order等)。

5.【强制】创建数据库时必须显式指定字符集,并且字符集只能是utf8或者utf8mb4。

创建数据库SQL举例(MySQL):CREATE DATABASE crm_fundDEFAULT CHARACTER SET 'utf8'

6.【建议】对于程序连接数据库账号,遵循权限最小原则。

使用数据库账号只能在一个DB下使用,不准跨库。程序使用的账号原则上不准有drop权限 。

7.【建议】临时库以 tmp_ 为前缀,并以日期为后缀;备份库以bak_为前缀,并以日期为后缀。

设计规范-表、列

字符和备注

1.【强制】创建表时必须显式指定字符集为utf8或utf8mb4。

2.【强制】创建表时必须显式指定表存储引擎类型。如无特殊需求,一律为InnoDB。

3.【强制】建表必须有注释comment。

4.【强制】禁止在数据库中存储明文密码。

5.【推荐】如果修改字段含义或对字段表示的状态追加时,需要及时更新字段注释。

命名

1.【强制】表名、字段名必须使用小写字母或数字,禁止出现数字开头禁止两个下划线中间只出现数字。数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑。

说明:MySQL 在 Windows 下不区分大小写,但在 Linux 下默认是区分大小写。因此,数据库名、表名、字段名,都不允许出现任何大写字母,避免节外生枝。

正例:aliyun_admin,rdc_config,level3_name

反例:AliyunAdmin,rdcConfig,level_3_name

2.【强制】表名不使用复数名词。

说明:表名应该仅仅表示表里面的实体内容,不应该表示实体数量,对应于 DO 类名也是单数形式,符合表达习惯。

3.【建议】表名要求有模块名强相关,同一模块的表名尽量使用统一前缀。比如:crm_fund_item。

4.【推荐】表的命名最好是遵循"业务名称_表的作用"。

正例:alipay_task / force_project / trade_config / tes_question

5.【推荐】库名与应用名称尽量一致。

6.【强制】表达是与否概念的字段,必须使用 is_xxx 的方式命名,数据类型是 unsigned tinyint(1 表示是,0 表示否)。

注意:POJO 类中的任何布尔类型的变量,都不要加 is 前缀,所以,需要在设置从 is_xxx 到 Xxx 的映射关系。数据库表示是与否的值,使用 tinyint 类型,坚持 is_xxx 的命名方式是为了明确其取值含义与取值范围。

说明:任何字段如果为非负数,必须是 unsigned。

正例:表达逻辑删除的字段名 is_deleted,1 表示删除,0 表示未删除。是否为enabled的会员的字段命名为is_enabled。

7.【强制】表名、列名禁止使用关键字,如 type、order、desc、range、match、delayed 等,请参考 MySQL 官方保留字。

8.【强制】字段命名应尽可能使用表达实际含义的英文单词或缩写。如:公司ID,不要使用corporation_id, 而用corp_id 即可。

9.【强制】主键索引名为 pk_字段名;唯一索引名为 uk_字段名;普通索引名则为 idx_字段名。

说明:pk_即 primary key;uk_即 unique key;idx_即 index 的简称。

10.【建议】 中间表(或临时表)用于保留中间结果集,名称以tmp_开头。备份表用于备份或抓取源表快照,名称以bak_开头。中间表和备份表定期清理。

字段

1.【强制】表必备三字段:id,create_time,update_time。

说明:其中 id 必为主键,类型为 bigint unsigned、单表时自增、步长为 1。create_time,update_time 的类型均为datetime 类型,前者现在时表示主动式创建,后者过去分词表示被动式更新。

2.【强制】在数据库中不能使用物理删除操作,要使用逻辑删除。

说明:逻辑删除在数据删除后可以追溯到行为操作。不过会使得一些情况下的唯一主键变得不唯一,需要根据情况来酌情解决。

3.【推荐】字段允许适当冗余,以提高查询性能,但必须考虑数据一致。冗余字段应遵循:

1)不是频繁修改的字段。

2)不是唯一索引的字段。

3)不是 varchar 超长字段,更不能是 text 字段。

4.【强制】禁止在数据库中存储图片、文件等大的二进制数据。

通常文件很大,短时间内造成数据量快速增长,数据库进行数据库读取时,通常会进行大量的随机IO操作,文件很大时,IO操作很耗时。通常存储于文件服务器,数据库只存储文件地址信息。

5.【强制】建表时关于主键:表必须有主键,强制要求主键为id,类型为int或bigint,且为auto_increment 建议使用unsigned无符号型。标识表里每一行主体的字段不要设为主键,建议设为其他字段如user_id,order_id等,并建立unique key索引。因为如果设为主键且主键值为随机插入,则会导致innodb内部页分裂和大量随机I/O,性能下降。

6.【建议】表中所有字段尽量都是NOT NULL属性,业务可以根据需要定义DEFAUL值。因为使用NULL值会存在每一行都会占用额外存储空间、数据迁移容易出错、聚合函数计算结果偏差等问题。

数据格式

1.【强制】小数类型为 decimal,禁止使用 float 和 double。

说明:在存储的时候,float 和 double 都存在精度损失的问题,很可能在比较值的时候,得到不正确的结果。如果存储的数据范围超过 decimal 的范围,建议将数据拆成整数和小数并分开存储。

2.【强制】如果存储的字符串长度几乎相等,使用 char 定长字符串类型。

3.【强制】varchar 是可变长字符串,不预先分配存储空间,长度不要超过 5000,如果存储长度大于此值,定义字段类型为 text,独立出来一张表,用主键来对应,避免影响其它字段索引率。

4.【推荐】单表行数超过 500 万行或者单表容量超过 2GB,才推荐进行分库分表。

说明:如果预计三年后的数据量根本达不到这个级别,请不要在创建表时就分库分表。

5.【参考】合适的字符存储长度,不但节约数据库表空间、节约索引存储,更重要的是提升检索速度。

正例:无符号值可以避免误存负数,且扩大了表示范围:

对象 年龄区间 类型 字节 表示范围
150岁之内 tinyint unsigned 1 无符号值:0 到 255
数百岁 smallint unsigned 2 无符号值:0 到 65535
恐龙化石 数千万年 int unsigned 4 无符号值:0 到约 43 亿
太阳 约50亿年 bigint unsigned 8 无符号值:0 到约 10 的 19 次方

6.【强制】所有存储相同数据的列名和列类型必须一致,避免隐式转换(一般作为关联列,如果查询时关联列类型不一致会自动进行数据类型隐式转换,会造成列上的索引失效,导致查询效率降低)。

7.【建议】表要有预留字段。可评估预留1-3个字段,以防后期表扩容变更。

8.【建议】定长和非定长数据类型的选择。decimal不会损失精度,存储空间会随数据的增大而增大。double占用固定空间,较大数的存储会损失精度。非定长的还有varchar、text。

9.【建议】优先选择符合存储需要的最小的数据类型、避免使用ENUM类型。

10.【建议】使用TIMESTAMP存储时间、DECIMAL代替FLOAT和DOUBLE存储精确浮点数、使用UNSIGNED存储非负整数、使用INT UNSIGNED存储IPV4。

11.【建议】尽可能不使用TEXT、BLOB类型。对于报文之类的大文本,可以用TEXT、BLOB类型,建议将该列单独设计为一张表,并通过关联字段与主表关联进行查询或其他操作。

12.【建议】特定字段类型的选择建议。

1)仅存储年使用YEAR类型,日期使用DATE类型。

2)时间类型使用datetime,不要使用timestmp。

3)钱币等精确浮点类型使用DECIMAL类型。

4)数值字段增长上限不大,不使用BIGINT。

sql 复制代码
--【示范】一个较为规范的建表语句

CREATE TABLE user_info (
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',
`user_id` bigint(11) NOT NULL COMMENT '用户id',
`username` varchar(45) NOT NULL COMMENT '真实姓名',
`email` varchar(30) NOT NULL COMMENT '用户邮箱',
`nickname` varchar(45) NOT NULL COMMENT '昵称',
`birthday` date NOT NULL COMMENT '生日',
`sex` tinyint(4) DEFAULT '0' COMMENT '性别',
`short_introduce` varchar(150) DEFAULT NULL COMMENT '一句话介绍自己,最多50个汉字',
`user_resume` varchar(300) NOT NULL COMMENT '用户提交的简历存放地址',
`user_register_ip` int NOT NULL COMMENT '用户注册时的源ip',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE
CURRENT_TIMESTAMP COMMENT '修改时间',
`user_review_status` tinyint NOT NULL COMMENT '用户资料审核状态,1为通过,2为审核中,3为未 通过,4为还未提交审核',

PRIMARY KEY (`id`),
UNIQUE KEY `uniq_user_id` (`user_id`),
KEY `idx_username`(`username`),
KEY `idx_create_time_status`(`create_time`,`user_review_status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='网站用户基本信息'

设计规范-索引

1.【强制】InnoDB表必须主键为id int/bigint auto_increment,且主键值禁止被更新。

2.【强制】InnoDB和MyISAM存储引擎表,索引类型必须为BTREE。

3.【强制】业务上具有唯一特性的字段,即使是组合字段,也必须建成唯一索引。

说明:不要以为唯一索引影响了 insert 速度,这个速度损耗可以忽略,但提高查找速度是明显的;另外,即使在应用层做了非常完善的校验控制,只要没有唯一索引,根据墨菲定律,必然有脏数据产生。

4.【强制】超过三个表禁止 join。需要 join 的字段,数据类型保持绝对一致;多表关联查询时,保证被关联的字段需要有索引。

说明:即使双表 join 也要注意表索引、SQL 性能。

5.【强制】在 varchar 字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据实际文本区分度决定索引长度。

说明:索引的长度与区分度是一对矛盾体,一般对字符串类型数据,长度为 20 的索引,区分度会高达 90%以上,可以使用 count(distinct left(列名,索引长度)) / count(星) 的区分度来确定。

6.【强制】页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决。

说明:索引文件具有 B-Tree 的最左前缀匹配特性,如果左边的值未确定,那么无法使用此索引。

7.【推荐】建组合索引的时候,区分度最高的在最左边。

正例:如果 where a = ? and b = ?,a 列的几乎接近于唯一值,那么只需要单建 idx_a 索引即可。

说明:存在非等号和等号混合判断条件时,在建索引时,请把等号条件的列前置。如:where c > ? and d = ? 那么即使 c 的区分度更高,也必须把 d 放在索引的最前列,即建立组合索引 idx_d_c。

8.【推荐】防止因字段类型不同造成的隐式转换,导致索引失效。

9.【参考】创建索引时避免有如下极端误解:

1)索引宁滥勿缺。认为一个查询就需要建一个索引。

2)吝啬索引的创建。认为索引会消耗空间、严重拖慢记录的更新以及行的新增速度。

3)抵制唯一索引。认为唯一索引一律需要在应用层通过"先查后插"方式解决。

10.【建议】主键的名称以pk_开头,唯一键以uni_或uk_开头,普通索引以idx_开头,一律使用小写格式,以字段的名称或缩写作为后缀。

11.【建议】多单词组成的columnname,取前几个单词首字母,加末单词组成column_name。如:

sample 表 member_id 上的索引:idx_sample_mid。

12.【强制】单个表上的索引个数不能超过5个。

13.【建议】在建立索引时,多考虑建立联合索引,并把区分度最高的字段放在最前面。

14.【建议】在多表 JOIN 的SQL里,保证被驱动表的连接列上有索引,这样JOIN 执行效率最高。

15.【强制】建表或加索引时,保证表里互相不存在冗余索引。比如:如果表里已经存在key(a,b),则key(a)为冗余索引,需要删除。

16.【强制】不使用更新频繁的列作为主键,如无特殊要求,使用自增id作为主键。对于并发插入量较大且需要物理主键的表,可以通过类似JAVA里的guid键值来代替。

17.【强制】索引创建选择唯一性较强的字段。

18.【建议】索引选择数据类型较短的字段。

19.【建议】尽量避免使用外键,容易产生死锁,由上层应用程序保证约束。

20.【建议】筛选text 或较长varchar类型字段,需使用全文索引。

21.【建议】全文索引必须使用match函数, AGAINST函数,不支持%通配符匹配

sql 复制代码
例:select * from articles where match(title, body) against('database' in natural language mode);

22.【强制】重要的SQL语句必须被索引,例如:update\delete语句的where条件列;order by \group by\distinct字段。

23.【建议】索引列建议

1)出现在SELECT、UPDATE、DELETE语句的WHERE从句中的列;

2)包含在ORDER BY、GROUP BY、DISTINCT中的字段;

3)多表JOIN的关联列;

注意:并不要将符合1和2中的字段的列都建立一个索引,通常将1、2中的字段建立联合索引效果更好。

24.【建议】索引列顺序建议

1)区分度最高的放在联合索引的最左侧(区分度=列中不同值的数量/列的总行数)

2)尽量把字段长度小的列放在联合索引的最左侧(因为字段长度越小,一页能存储的数据量越大,IO性能也就越好)

3)使用最频繁的列放到联合索引的左侧(这样可较少的建立一些索引)

跟索引相关的SQL优化

1.【强制】如果有 order by 的场景,请注意利用索引的有序性。order by 最后的字段是组合索引的一部分,并且放在索引组合顺序的最后,避免出现 filesort 的情况,影响查询性能。

正例:where a = ? and b = ? order by c;索引:a_b_c

反例:索引如果存在范围查询,那么索引有序性无法利用,如:WHERE a > 10 ORDER BY b;索引 a_b 无法排序。

2.【强制】利用覆盖索引来进行查询操作,避免回表。

说明:如果一本书需要知道第 11 章是什么标题,会翻开第 11 章对应的那一页吗?目录浏览一下就好,这个目录就是起到覆盖索引的作用。

3.【推荐】利用延迟关联或者子查询优化超多分页场景。

说明:MySQL 分页并不是跳过 offset 行,而是取 offset+N 行,然后返回放弃前 offset 行,返回 N 行,那当 offset 特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过特定阈值的页数进行 SQL 改写。

正例:先快速定位需要获取的 id 段,然后再关联:

sql 复制代码
select t1.* 
from 表1 as t1 , (select id from 表1 where 条件 LIMIT 100000, 20) as t2 
where t1.id = t2.id

4.【推荐】SQL 性能优化的目标:至少要达到 range 级别,要求是 ref 级别,如果可以是 const 最好。

说明:

1)consts 单表中最多只有一个匹配行(主键或者唯一索引),在优化阶段即可读取到数据。

Java 开发手册(黄山版)

2)ref 指的是使用普通的索引(normal index)。

3)range 对索引进行范围检索。

反例:explain 表的结果,type = index,索引物理文件全扫描,速度非常慢,这个 index 级别比较 range 还低,与全表扫描是小巫见大巫。

设计规范-视图

1.【强制】数据库不能包含具有相同名称的表和视图。

2.【强制】定义中不能引用TEMPORARY表,不能创建TEMPORARY视图。

3.【强制】不能将触发程序与视图关联在一起。

4.【建议】视图以v_name命名。

设计规范-存储过程

在MySQL数据库中尽量避免使用存储过程,Oracle数据库中午要求。

在存储过程中,MySQL禁止使用下述语句:

CHECK TABLES

LOCK TABLES, UNLOCK TABLES

LOAD DATA, LOAD TABLE

OPTIMIZE TABLE

SQL预处理语句(PREPARE、EXECUTE、DEALLOCATE PREPARE),目前仅适用于存储过程;不适用于存储函数和触发器;也不适用于在存储函数或者触发器里面调用含有预处理语句的存储过程。

创建存储过程以proc_开头命名,函数以 func_开头命名。

设计规范-触发器

建议禁止使用触发器,触发器可以理解为是一个隐藏的存储过程,它不需要调用,不需要显示调用,维护起来容易被忽略。可以使用存储过程来替代。

设计规范-安全规范

用户权限管理:按照最小权限原则分配用户权限,避免过多权限导致的安全风险。

加密敏感数据:对于敏感数据,建议进行加密处理。

防范SQL注入:使用预编译查询,并避免动态生成SQL语句。

审计和日志记录:记录关键操作日志,确保可追溯性。

数据库架构设计原则

一、高可用架构选择

设计数据库时,考虑实现高可用性方案,如数据库镜像、复制和集群技术,避免单节点故障引起的业务影响。采用主从复制或集群技术,确保数据的高可用性和实时同步。配置自动故障切换机制,如主备切换,保证系统在故障发生时能迅速恢复。

二、扩展性

对于系统来说扩展性很重要,尽量做到水平扩展。避免过度依赖纵向扩展,同时具备纵向,横向扩展的能力,例如无状态应用应该多套负载均衡多活部署,数据库分库架构。架构应该尽可能地分散负载,减少单点故障的风险。

三、安全性策略

访问控制:严格控制数据库访问权限,遵循最小权限原则。

加密存储:采用合适的加密算法加密核心数据,防止黑客攻击和数据泄露。

日志审计:启用数据库日志,记录用户操作和系统事件,以便安全审计和问题追溯。

四、数据完整性策略

必须遵循数据库设计的第二范式,根据业务需要尽量满足第三范式

数据完整性尽量通过业务逻辑实现,数据库设计应尽量避免使用大量的外键约束,避免使用触发器。

五、规范化设计与性能之间的权衡策略

数据的标准化有助于消除数据库中的数据冗余。如果数据几余低数据的一致性容易得到保证,如无特殊理由,OLTP系统的设计应当遵循第三范式,对于 OLAP 系统,为了减少表间连接查询的操作,提高系统的响应时间,合理的数据几余是必要的。

六、数据生命周期管理

数据归档:对历史数据和不常使用的数据进行归档处理,减少主库的负担。

数据清理:定期清理过期和无用的数据,保持数据库的整洁。

七、数据备份策略

备份策略:制定完善的备份策略,包括全量、增量备份及异地备份。

SQL 语句

1.【强制】不要使用 count(列名) 或 count(常量) 来替代 count(※),count(※) 是 SQL92 定义的标准统计行数的语法,跟数据库无关,跟 NULL 和非 NULL 无关。

说明:count(※) 会统计值为 NULL 的行,而 count(列名) 不会统计此列为 NULL 值的行。

2.【强制】count(distinct col) 计算该列除 NULL 之外的不重复行数,注意 count(distinct col1 , col2) 如

果其中一列全为 NULL,那么即使另一列有不同的值,也返回为 0。

3.【强制】当某一列的值全是 NULL 时,count(col) 的返回结果为 0;但 sum(col) 的返回结果为 NULL,因此使用 sum() 时需注意 NPE 问题。

正例:可以使用如下方式来避免 sum 的 NPE 问题:select ifnull(sum(column) , 0) from table;

4.【强制】使用 ISNULL() 来判断是否为 NULL 值。

说明:NULL 与任何值的直接比较都为 NULL。

1)NULL<>NULL 的返回结果是 NULL,而不是 false。

2)NULL=NULL 的返回结果是 NULL,而不是 true。

3)NULL<>1 的返回结果是 NULL,而不是 true。

反例:在 SQL 语句中,如果在 null 前换行,影响可读性。

select * from table where column1 is null and column3 is not null;而 ISNULL(column) 是一个整体,简洁易懂。

从性能数据上分析,ISNULL(column) 执行效率更快一些。

5.【强制】代码中写分页查询逻辑时,若 count 为 0 应直接返回,避免执行后面的分页语句。

6.【强制】不得使用外键与级联,一切外键概念必须在应用层解决。

说明:(概念解释)学生表中的 student_id 是主键,那么成绩表中的 student_id 则为外键。如果更新学生表中的 student_id,同时触发成绩表中的 student_id 更新,即为级联更新。外键与级联更新适用于单机低并发,不适合分布式、高并发集群;级联更新是强阻塞,存在数据库更新风暴的风险;外键影响数据库的插入速度。

7.【强制】禁止使用存储过程,存储过程难以调试和扩展,更没有移植性。

8.【强制】数据订正(特别是删除或修改记录操作)时,要先 select,避免出现误删除的情况,确认无误才

能执行更新语句。

9.【强制】对于数据库中表记录的查询和变更,只要涉及多个表,都需要在列名前加表的别名(或表名)进行限定。

说明:对多表进行查询记录、更新记录、删除记录时,如果对操作列没有限定表的别名(或表名),并且操作列在多个表中存在时,就会抛异常。

正例:select t1.name from first_table as t1 , second_table as t2 where t1.id = t2.id;

反例:在某业务中,由于多表关联查询语句没有加表的别名(或表名)的限制,正常运行两年后,最近在某个表中增加一个同名字段,在预发布环境做数据库变更后,线上查询语句出现出 1052 异常:

Column 'name' infield list is ambiguous。

10.【推荐】SQL 语句中表的别名前加 as,并且以 t1、t2、t3、...的顺序依次命名。

说明:

1)别名可以是表的简称,或者是依照表在 SQL 语句中出现的顺序,以 t1、t2、t3 的方式命名。

2)别名前加 as 使别名更容易识别。

正例:select t1.name from first_table as t1 , second_table as t2 where t1.id = t2.id;

11.【推荐】in 操作能避免则避免,若实在避免不了,需要仔细评估 in 后边的集合元素数量,控制在1000 个之内。

12.【参考】因国际化需要,所有的字符存储与表示,均采用 utf8 字符集,那么字符计数方法需要注意。

说明:

select length("轻松工作");--返回为 12

select character_length("轻松工作");--返回为 4

如果需要存储表情,那么选择 utf8mb4 来进行存储,注意它与 utf8 编码的区别。

13.【参考】truncate table 比 delete 速度快,且使用的系统和事务日志资源少,但 truncate 无事务且不触发 trigger,有可能造成事故,故不建议在开发代码中使用此语句。

说明:truncate table 在功能上与不带 where 子句的 delete 语句相同

14.【强制】程序端 select 语句必须指定具体字段名称,禁止写成*。

15.【强制】禁止like "%abs"做where条件,会全表扫描且不能用索引。

16.【强制】Where条件里不要对列使用函数,不会引用索引,除非谓词列已有函数索引。

17.【强制】禁止单条语句同时更新多个表。

18.【强制】杜绝大事务,事务要尽量简单,整个事务的时间长度不要太长。

19.【建议】能确定返回结果只有一条时,使用 limit 1(LIMIT分页注意效率,LIMIT越大,效率越低)。

20.【建议】少用子查询,改用JOIN(子查询要在内存里建临时表)。

21.【建议】多表JOIN的字段,区分度最大的字段放在前面。

22.【建议】只读查询语句不要显式开启事务,例如不要加begin或start transaction。

23.【建议】多条INSERT语句使用bulk insert提交(INSERT INTO table VALUES(),(),()......)。

24.【建议】避免大表join。

25.【建议】SQL语句不可以出现隐式转换,比如 select id from 表 where id='1',其中id列为非字符类型。

26.【建议】除非必要,避免使用!=等非等值操作符,会导致用不到索引。

27.【建议】程序端insert语句指定具体字段名称,不建议写成INSERT INTO t1 VALUES(...)。

28.【建议】除静态表或小表(100行以内),DML语句必须有WHERE条件,且使用索引查找。

29.【建议】INSERT INTO...VALUES(XX),(XX),(XX)... 这里XX的值不要超过5000个。 值过多虽然上线很快,但会引起主从同步延迟。

30.【建议】SELECT语句避免使用UNION,推荐使用UNION ALL,并且UNION子句个数限制在5个以内。在明显不会有重复值时使用UNION ALL而不是UNION。UNION会把两个结果集的所有数据放到临时表中后再进行去重操作,UNION ALL不会再对结果集进行去重操作。

31.【建议】线上环境,多表JOIN不要超过5个表。

32.【建议】减少使用ORDER BY,和业务沟通能不排序就不排序,或将排序放到程序端去做。ORDER BY、GROUP BY、DISTINCT 这些语句较为耗费CPU,数据库的CPU资源是极其宝贵的。

33.【建议】包含了ORDER BY、GROUP BY、DISTINCT 这些查询的语句,WHERE 条件过滤出来的结果集请保持在1000行以内,否则SQL会很慢。

34.【建议】对单表的多次alter操作必须合并为一次。对于超过100W行的大表进行alter table,必须经过DBA审核,并在业务低峰期执行,多个alter需整合在一起。 因为alter table会产生表锁 ,期间阻塞对于该表的所有写入,对于业务可能会产生极大影响。

35.【建议】批量操作数据时,需要控制事务处理间隔时间,进行必要的sleep。

36.【建议】事务里包含SQL不超过5个。因为过长的事务会导致锁数据较久,MySQL内部缓存、连接消耗过多等问题。

37.【建议】事务里更新语句尽量基于主键或UNIQUE KEY,如 UPDATE... WHERE id=XX。否则会产生间隙锁,内部扩大锁定范围,导致系统性能下降,产生死锁。

38.【建议】避免使用insert into ...on duplicate key update...在高并发环境下,会造成主从不一致。

39.【建议】多表JOIN时需要注意以下:

1)区分度最大的字段放在前面;

2)核心SQL优先考虑覆盖索引;

3)避免冗余和重复索引;

4)索引要综合评估数据密度和分布以及考虑查询和更新比例。

40.【建议】超100万行的批量写(UPDATE、DELETE、INSERT)操作,要分批多次进行操作。

41.【建议】对于大表使用pt-online-schema-change修改表结构。可避免大表修改产生的主从延迟、在对表字段进行修改时进行锁表。

相关推荐
modelsetget1 分钟前
MySQL锁机制详细笔记
数据库·mysql·面试·数据库锁
不爱洗脚的小滕1 小时前
【MySQL】SQL注入的介绍
数据库·sql·mysql
xiaogengtongxu2 小时前
Mysql中间件和高可用
数据库·mysql·中间件
Xpccccc2 小时前
MySQL数据类型
数据库·mysql
.周周3 小时前
mysql数据表时间字段自动存时间
数据库·mysql
vx_Biye_Design3 小时前
驾校管理系统-计算机毕业设计源码49777
java·css·vue.js·spring boot·mysql·ajax·mvc
baozongwi3 小时前
ctfshow sqli-libs web561--web568
数据库·经验分享·python·sql·mysql·web安全
skyshandianxia4 小时前
java面试八股之MySQL怎么优化查询语句
java·mysql·面试
醇氧4 小时前
【MySQL】哪些平台支持MySQL 数据库
数据库·mysql
skyshandianxia5 小时前
Java面试八股之MySQL存储货币数据,用什么类型合适
mysql·面试·职场和发展