特别是在大数据量、高并发的场景下,如何确保MySQL数据库的稳定运行和高效性能,成为每个技术团队必须面对的重要课题
58到家的MySQL军规,正是基于这一背景,经过实践检验的一套数据库使用规范
本文将详细解读这些军规,帮助大家更好地理解和应用,从而打造高效、稳定的数据库架构
一、基础规范:奠定坚实基石 1. 必须使用InnoDB存储引擎 InnoDB是MySQL的默认存储引擎,它支持事务处理、行级锁定和外键约束,具备更好的并发性能和故障恢复能力
此外,InnoDB在CPU及内存缓存页方面进行了优化,使得资源利用率更高
在高并发、大数据量的互联网业务中,InnoDB存储引擎无疑是最佳选择
2. 必须使用utf8mb4字符集 utf8mb4是utf8的超集,能够存储4字节的字符,包括各种表情符号
使用utf8mb4字符集,可以避免乱码风险,同时节省存储空间
在互联网业务中,用户生成的内容日益丰富多样,使用utf8mb4字符集能够更好地满足这些需求
3. 禁止使用存储过程、视图、触发器和Event 在高并发、大数据量的互联网业务中,架构设计思路是“解放数据库CPU,将计算转移到服务层”
存储过程、视图、触发器和Event等功能虽然强大,但在并发量大的情况下,它们可能拖慢数据库性能
因此,这些功能应被禁止使用,以确保数据库的高效运行
4. 禁止存储大文件或大照片 数据库擅长的是存储与索引,而不是处理大文件或大照片
这些大文件应该存储在文件系统或对象存储系统中,数据库中只需存储其路径即可
这样做可以避免数据库承受不必要的负担,提高整体性能
二、命名规范:清晰明了,易于管理 1. 数据库连接规范 只允许使用内网域名连接数据库,而不是IP地址
线上环境、开发环境、测试环境的数据库内网域名应遵循命名规范
例如,业务名称为xxx的线上环境数据库域名为a.xxx.db,开发环境为a.xxx.rdb,测试环境为a.xxx.tdb
从库在名称后加-s标识,备库在名称后加-ss标识
2. 库名、表名、字段名规范 库名、表名、字段名应使用小写字母和下划线分隔,长度不超过32个字符,且必须见名知意
禁止拼音和英文混用
表名使用t_xxx格式,非唯一索引名使用idx_xxx格式,唯一索引名使用uniq_xxx格式
这样的命名规范有助于团队成员快速理解数据库结构,提高开发效率
三、表设计规范:优化结构,提升性能 1. 单实例表数目和单表列数目限制 单实例表数目应小于500个(某些升级版军规建议控制在2000个以内),单表列数目应小于30个
过多的表和列会增加数据库的复杂性和管理难度,降低性能
2. 主键设计 表必须有主键,推荐使用UNSIGNED整数类型
主键递增可以提高插入性能,避免page分裂,减少表碎片,提升空间和内存的使用效率
同时,较短的数据类型作为主键可以减少索引的磁盘空间占用,提高索引的缓存效率
3. 禁止使用外键 外键会导致表与表之间耦合,影响update和delete等SQL性能,甚至可能造成死锁
在高并发情况下,外键容易成为数据库性能的瓶颈
因此,应禁止使用外键,如果需要保证数据完整性,应由应用程序实现
四、字段设计规范:精细管理,避免冗余 1. 字段定义 必须把字段定义为NOT NULL并设默认值
NULL值会使索引、索引统计和值比较变得更加复杂,增加数据库处理的复杂性
同时,NULL值需要更多的存储空间,并且在查询时只能使用IS NULL或IS NOT NULL操作符,限制了查询的灵活性
2. 数据类型选择 根据业务场景选择合适的数据类型
例如,对于字段长度固定或近似的业务场景,适合使用CHAR类型以减少碎片并提高查询性能;对于字段长度相差较大或更新较少的业务场景,适合使用VARCHAR类型以减少空间占用
此外,应使用INT UNSIGNED存储IPv4地址,使用VARCHAR(20)存储手机号等
3. 禁止使用TEXT、BLOB类型 TEXT和BLOB类型会浪费更多的磁盘和内存空间,非必要的大量大字段查询会淘汰掉热数据,导致内存命中率急剧降低,影响数据库性能
因此,应禁止使用这些类型,除非确实有必要存储大量文本或二进制数据
4. 禁止使用小数存储货币 小数存储货币容易导致金额计算不准确
应使用整数类型存储货币金额,以避免精度损失和计算错误
五、索引设计规范:合理构建,高效查询 1. 索引数量控制 单表索引建议控制在5个以内
过多的索引会影响写性能,并在生成执行计划时降低性能
同时,异常复杂的查询需求可以选择更适合的存储方式,如Elasticsearch等
2. 索引字段选择 禁止在更新十分频繁、区分度不高的属性上建立索引
更新频繁的字段建立索引会大大降低数据库性能;而区分度不高的属性建立索引则不能有效过滤数据,性能与全表扫描类似
建立组合索引时,必须把区分度高的字段放在前面,以更有效地过滤数据
六、SQL使用规范:优化查询,提升效率 1. 禁止使用SELECT 只获取必要的字段,避免读取不需要的列增加CPU、IO、NET消耗
同时,指定字段能有效利用索引覆盖,提高查询效率
在表结构变更时,指定字段查询也能保证对应用程序无影响
2. 禁止使用INSERT INTO ... VALUES() 必须显示指定插入的列属性
这样做同样是为了避免在表结构变更时出现程序BUG,并确保数据的准确性
3. 禁止使用属性隐式转换 隐式类型转换会使索引失效,导致全表扫描
因此,在编写SQL语句时,应确保数据类型的一致性,避免隐式转换的发生
4. 禁止在WHERE条件的属性上使用函数或表达式 这同样会导致索引失效,全表扫描
正确的做法是将函数或表达式应用到常量上,而不是字段上
例如,将SELECT uid FROMt_user WHEREfrom_unixtime(day)>=‘2017-02-15’改写为SELECT uid FROM t_user WHERE day>= unix_timestamp(‘2017-02-15 00:00:00’)
5. 禁止负向查询以及%开头的模糊查询 负向查询条件(如NOT、!=、<>、!<、!>、NOT IN、NOT LIKE等)和%开头的模糊查询都会导致全表扫描
因此,应尽量避免使用这些查询条件,以提高查询效率
6. 禁止大表JOIN和子查询 大表JOIN和子查询会产生临时表,消耗较多内存与CPU资源,极大影响数据库性能
在可能的情况下,应尽量避免使用这些操作,或者通过优化查询逻辑来减少其影响
7. 禁止使用OR条件 旧版本MySQL的OR查询不能命中索引
即使在新版本中能够命中索引,也应尽量避免使用OR条件,以减少数据库的处理负担
正确的做法是使用IN查询来替代OR条件
但需要注意的是,IN查询的值应少于50个,以避免性能下降
结语:遵循军规,打造高效数据库架构 58到家的MySQL军规是一套经过实践检验的数据库使用规范,它涵盖了基础规范、命名规范、表设计规范、字段设计规范、索引设计规范以及SQL使用规范等多个方面
遵循这些军规,可以帮助我们打造高效、稳定的数据库架构,提升业务系统的性能和可靠性
在互联网业务迅速发展的今天,这些军规无疑具有重要的指导意义和实践价值
让我们共同努力,遵循58 MySQL军规,为业务的成功保驾护航!