MySQL数据库规范(完整版)
⼀、数据库命令规范
1)所有数据库对象名称必须使⽤⼩写字母并⽤下划线分割
2)所有数据库对象名称禁⽌使⽤MySQL保留关键字(如果表名中包含关键字查询时,需要将其⽤单引号括起来)
3 )数据库对象的命名要能做到见名识意,并且最后不要超过32个字符
4 )临时库表必须以tmp_为前缀并以⽇期为后缀,备份表必须以bak_为前缀并以⽇期(时间戳)为后缀
5 )所有存储相同数据的列名和列类型必须⼀致(⼀般作为关联列,如果查询时关联列类型不⼀致会⾃动进⾏数据类型隐式转换,会造成列上的索 引失效,导致查询效率降低)
⼆、数据库基本设计规范
1)所有表必须使⽤Innodb存储引擎
没有特殊要求(即Innodb⽆法满⾜的功能如:列存储,存储空间数据等)的情况下,所有表必须使⽤Inn
odb存储引擎(MySQL5.5之前默认使⽤Myisam,5.6以后默认的为Innodb)Innodb ⽀持事务,⽀持⾏级锁,更好的恢复性,⾼并发下性能更好
2)数据库和表的字符集统⼀使⽤UTF8
兼容性更好,统⼀字符集可以避免由于字符集转换产⽣的乱码,不同的字符集进⾏⽐较前需要进⾏转换会造成索引失效
3)所有表和字段都需要添加注释
使⽤comment从句添加表和列的备注 从⼀开始就进⾏数据字典的维护
4)尽量控制单表数据量的⼤⼩,建议控制在500万以内
500万并不是MySQL数据库的限制,过⼤会造成修改表结构,备份,恢复都会有很⼤的问题
可以⽤历史数据归档(应⽤于⽇志数据),分库分表(应⽤于业务数据)等⼿段来控制数据量⼤⼩
5)谨慎使⽤MySQL分区表
数据库优化sql语句分区表在物理上表现为多个⽂件,在逻辑上表现为⼀个表 谨慎选择分区键,跨分区查询效率可能更低
建议采⽤物理分表的⽅式管理⼤数据
6)尽量做到冷热数据分离,减⼩表的宽度
MySQL限制每个表最多存储4096列,并且每⼀⾏数据的⼤⼩不能超过65535字节 减少磁盘IO,保证热数据的内存缓存命中率(表越宽,把表装载进内存缓冲池时所占⽤的内存也就越⼤,也会消耗更多的IO) 更有效的利⽤缓存,避免读⼊⽆⽤的冷数据 经常⼀起使⽤的列放到⼀个表中(避免更多的关联操作)
7)禁⽌在表中建⽴预留字段
预留字段的命名很难做到见名识义 预留字段⽆法确认存储的数据类型,所以⽆法选择合适的类型 对预留字段类型的修改,会对表进⾏锁定
8)禁⽌在数据库中存储图⽚,⽂件等⼤的⼆进制数据
通常⽂件很⼤,会短时间内造成数据量快速增长,数据库进⾏数据库读取时,通常会进⾏⼤量的随机IO操作,⽂件很⼤时,IO操作很耗时 通常存储于⽂件服务器,数据库只存储⽂件地址信息
9)禁⽌在线上做数据库压⼒测试
10)禁⽌从开发环境,测试环境直接连接⽣成环境数据库
三、数据库字段设计规范
1. 优先选择符合存储需要的最⼩的数据类型
原因:
列的字段越⼤,建⽴索引时所需要的空间也就越⼤,这样⼀页中所能存储的索引节点的数量也就越少也越少,在遍历时所需要的IO次数也就越多, 索引的性能也就越差
⽅法:
1)将字符串转换成数字类型存储,如:将IP地址转换成整形数据。
MySQL提供了两个⽅法来处理ip地址:
插⼊数据前,先⽤inet_aton把ip地址转为整型,可以节省空间。显⽰数据时,使⽤inet_ntoa把整型的ip地址转为地址显⽰即可。
2)对于⾮负型的数据(如⾃增ID、整型IP)来说,要优先使⽤⽆符号整型来存储
因为:⽆符号相对于有符号可以多出⼀倍的存储空间
VARCHAR(N)中的N代表的是字符数,⽽不是字节数
使⽤UTF8存储255个汉字 Varchar(255)=765个字节。过⼤的长度会消耗更多的内存
2. 避免使⽤TEXT、BLOB数据类型,最常见的TEXT类型可以存储64k的数据
建议把BLOB或是TEXT列分离到单独的扩展表中
MySQL内存临时表不⽀持TEXT、BLOB这样的⼤数据类型,如果查询中包含这样的数据,在排序等操作时,就不能使⽤内存临时表,必须使⽤磁盘临时表进⾏。
⽽且对于这种数据,MySQL还是要进⾏⼆次查询,会使sql性能变得很差,但是不是说⼀定不能使⽤这样的数据类型。
如果⼀定要使⽤,建议把BLOB或是TEXT列分离到单独的扩展表中,查询时⼀定不要使⽤select * ⽽
只需要取出必要的列,不需要TEXT列的数据时不要对该列进⾏查询。
TEXT或BLOB类型只能使⽤前缀索引
因为MySQL对索引字段长度是有限制的,所以TEXT类型只能使⽤前缀索引,并且TEXT列上是不能有默认值的。
3. 避免使⽤ENUM类型
修改ENUM值需要使⽤ALTER语句
ENUM类型的ORDER BY操作效率低,需要额外操作
禁⽌使⽤数值作为ENUM的枚举值
4. 尽可能把所有列定义为NOT NULL
原因:
索引NULL列需要额外的空间来保存,所以要占⽤更多的空间;
进⾏⽐较和计算时要对NULL值做特别的处理
5. 使⽤TIMESTAMP(4个字节)或DATETIME类型(8个字节)存储时间
TIMESTAMP 存储的时间范围 1970-01-01 00:00:01 ~ 2038-01-19-03:14:07。
TIMESTAMP 占⽤4字节和INT相同,但⽐INT可读性⾼
超出TIMESTAMP取值范围的使⽤DATETIME类型存储。
经常会有⼈⽤字符串存储⽇期型的数据(不正确的做法):
缺点1:⽆法⽤⽇期函数进⾏计算和⽐较
缺点2:⽤字符串存储⽇期要占⽤更多的空间
6. 同财务相关的⾦额类数据必须使⽤decimal类型
⾮精准浮点:float,double
精准浮点:decimal
Decimal类型为精准浮点数,在计算时不会丢失精度。占⽤空间由定义的宽度决定,每4个字节可以存储9位数字,并且⼩数点要占⽤⼀个字节。可⽤于存储⽐bigint更⼤的整型数据。
四、索引设计规范
1)限制每张表上的索引数量,建议单张表索引不超过5个
索引并不是越多越好!索引可以提⾼效率同样可以降低效率。
索引可以增加查询效率,但同样也会降低插⼊和更新的效率,甚⾄有些情况下会降低查询效率。
因为l优化器在选择如何优化查询时,会根据统⼀信息,对每⼀个可以⽤到的索引来进⾏评估,以⽣成出⼀个最好的执⾏计划,如果同时有很多个索引都可以⽤于查询,就会增加MySQL优化器⽣成执⾏计划的时间,同样会降低查询性能。
2)禁⽌给表中的每⼀列都建⽴单独的索引
5.6版本之前,⼀个sql只能使⽤到⼀个表中的⼀个索引,5.6以后,虽然有了合并索引的优化⽅式,但是还是远远没有使⽤⼀个联合索引的查询⽅式好
3)每个Innodb表必须有个主键
Innodb是⼀种索引组织表:数据的存储的逻辑顺序和索引的顺序是相同的。
每个表都可以有多个索引,但是表的存储顺序只能有⼀种 Innodb是按照主键索引的顺序来组织表的。
不要使⽤更新频繁的列作为主键,不适⽤多列主键(相当于联合索引) 不要使⽤UUID、MD5、HASH、字符串列作为主键(⽆法保证数据的顺序增长)。
主键建议使⽤⾃增ID值。
五、常见索引列建议
1)出现在SELECT、UPDATE、DELETE语句的WHERE从句中的列
2)包含在ORDER BY、GROUP BY、DISTINCT中的字段并不要将符合1和2中的字段的列都建⽴⼀个索引,通常将1、2中的字段建⽴联合索引效果更好
3)多表join的关联列
六、如何选择索引列的顺序
1)建⽴索引的⽬的是:希望通过索引进⾏数据查,减少随机IO,增加查询性能 ,索引能过滤出越少的数据,则从磁盘中读⼊的数据也就越少。
区分度最⾼的放在联合索引的最左侧(区分度=列中不同值的数量/列的总⾏数);
2)尽量把字段长度⼩的列放在联合索引的最左侧(因为字段长度越⼩,⼀页能存储的数据量越⼤,IO性能也就越好);
3)使⽤最频繁的列放到联合索引的左侧(这样可以⽐较少的建⽴⼀些索引)。
七、避免建⽴冗余索引和重复索引
因为这样会增加查询优化器⽣成执⾏计划的时间。
1)重复索引⽰例:primary key(id)、index(id)、unique index(id)
2)冗余索引⽰例:index(a,b,c)、index(a,b)、index(a)
⼋、优先考虑覆盖索引
1)对于频繁的查询优先考虑使⽤覆盖索引。
覆盖索引:就是包含了所有查询字段(where,select,ordery by,group by包含的字段)的索引
覆盖索引的好处:
2)避免Innodb表进⾏索引的⼆次查询
Innodb是以聚集索引的顺序来存储的,对于Innodb来说,⼆级索引在叶⼦节点中所保存的是⾏的主键信息,
如果是⽤⼆级索引查询数据的话,在查到相应的键值后,还要通过主键进⾏⼆次查询才能获取我们真实所需要的数据。⽽在覆盖索引中,⼆级索引的键值中可以获取所有的数据,避免了对主键的⼆次查询 ,减少了IO操作,提升了查询效率。
3)可以把随机IO变成顺序IO加快查询效率
由于覆盖索引是按键值的顺序存储的,对于IO密集型的范围查来说,对⽐随机从磁盘读取每⼀⾏的数据IO要少的多,因此利⽤覆盖索引在访问时也可以把磁盘的随机读取的IO转变成索引查的顺序IO。
九、索引SET规范
尽量避免使⽤外键约束
1)不建议使⽤外键约束(foreign key),但⼀定要在表与表之间的关联键上建⽴索引;
2)外键可⽤于保证数据的参照完整性,但建议在业务端实现;
3)外键会影响⽗表和⼦表的写操作从⽽降低性能。
⼗、数据库SQL开发规范
1)建议使⽤预编译语句进⾏数据库操作
预编译语句可以重复使⽤这些计划,减少SQL编译所需要的时间,还可以解决动态SQL所带来的SQL注⼊的问题 只传参数,⽐传递SQL 语句更⾼效 相同语句可以⼀次解析,多次使⽤,提⾼处理效率。
2)避免数据类型的隐式转换
隐式转换会导致索引失效。如:select name,phone from customer where id = '111';
3)充分利⽤表上已经存在的索引
避免使⽤双%号的查询条件。
如a like '%123%',(如果⽆前置%,只有后置%,是可以⽤到列上的索引的)
⼀个SQL只能利⽤到复合索引中的⼀列进⾏范围查询
如:有 a,b,c列的联合索引,在查询条件中有a列的范围查询,则在b,c列上的索引将不会被⽤到,在定义联合索引时,如果a列要⽤到范围查的话,就要把a列放到联合索引的右侧。
使⽤left join或 not exists来优化not in操作,因为not in 也通常会使⽤索引失效。
4)数据库设计时,应该要对以后扩展进⾏考虑
5)程序连接不同的数据库使⽤不同的账号,进制跨库查询
1. 为数据库迁移和分库分表留出余地
2. 降低业务耦合度
3. 避免权限过⼤⽽产⽣的安全风险
6)禁⽌使⽤SELECT * 必须使⽤SELECT <;字段列表> 查询
原因:
1. 消耗更多的CPU和IO以⽹络带宽资源
2. ⽆法使⽤覆盖索引
3. 可减少表结构变更带来的影响
7)禁⽌使⽤不含字段列表的INSERT语句
如:insert into values ('a','b','c');
应使⽤insert into t(c1,c2,c3) values ('a','b','c');
8.避免使⽤⼦查询,可以把⼦查询优化为join操作
通常⼦查询在in⼦句中,且⼦查询中为简单SQL(不包含union、group by、order by、limit从句)时,才可以把⼦查询转化为关联查询进⾏优化。
⼦查询性能差的原因:
1. ⼦查询的结果集⽆法使⽤索引,通常⼦查询的结果会被存储到临时表中,不论是内存临时表还是磁盘临时表都不会存在索引,所以查
询性能 会受到⼀定的影响;
2. 特别是对于返回结果集⽐较⼤的⼦查询,其对查询性能的影响也就越⼤;
3. 由于⼦查询会产⽣⼤量的临时表也没有索引,所以会消耗过多的CPU和IO资源,产⽣⼤量的慢查询。
9)避免使⽤JOIN关联太多的表
对于MySQL来说,是存在关联缓存的,缓存的⼤⼩可以由join_buffer_size参数进⾏设置。
在MySQL中,对于同⼀个SQL多关联(join)⼀个表,就会多分配⼀个关联缓存,如果在⼀个SQL中关联的表越多,所占⽤的内存也就越⼤。
如果程序中⼤量的使⽤了多表关联的操作,同时join_buffer_size设置的也不合理的情况下,就容易造成服务器内存溢出的情况,就会影响到服务器数据库性能的稳定性。
同时对于关联操作来说,会产⽣临时表操作,影响查询效率MySQL最多允许关联61个表,建议不超过5个。
10)减少同数据库的交互次数
数据库更适合处理批量操作 合并多个相同的操作到⼀起,可以提⾼处理效率
11)对应同⼀列进⾏or判断时,使⽤in代替or
in的值不要超过500个in操作可以更有效的利⽤索引,or⼤多数情况下很少能利⽤到索引。
12)禁⽌使⽤order by rand() 进⾏随机排序
会把表中所有符合条件的数据装载到内存中,然后在内存中对所有数据根据随机⽣成的值进⾏排序,并且可能会对每⼀⾏都⽣成⼀个随机值,如果满⾜条件的数据集⾮常⼤,就会消耗⼤量的CPU和IO及内存资源。
推荐在程序中获取⼀个随机值,然后从数据库中获取数据的⽅式
13)WHERE从句中禁⽌对列进⾏函数转换和计算
对列进⾏函数转换或计算时会导致⽆法使⽤索引。
· 不推荐:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。