一、涉及业务上的修改/删除数据,在获得业务方、CTO的邮件批准后方可执行,执行前提早作好备份,必要时可逆。java
二、全部上线需求必须走工单系统,口头通知视为无效。mysql
三、在对大表作表结构变动时,如修改字段属性会形成锁表,并会形成从库延迟,从而影响线上业务,必须在凌晨0:00 后业务低峰期执行,另统一用工具 pt-online-schema-change 避免锁表且下降延迟执行时间。sql
使用范例:数据库
#pt-online-schema-change --alter="add index IX_id_no(id_no)" \ --no-check-replication-filters --recursion-method=none --user=dba \ --password=123456 D=test,t=t1 --execute
对于MongoDB建立索引要在后台建立,避免锁表。后端
使用范例:网络
db.t1.createIndex({idCardNum:1},{background:1})
四、全部线上业务库均必须搭建MHA高可用架构,避免单点问题。架构
五、给业务方开权限时,密码要用MD5加密,至少16位。权限如没有特殊要求,均为select查询权限,并作库表级限制。并发
六、删除默认空密码帐号。分布式
delete from mysql.user where user='' and password=''; flush privileges;
七、汇总库开启Audit审计日志功能,出现问题时方可追溯。ide
八、禁止一个MySQL实例存放多个业务数据库,会形成业务耦合性太高,一旦出现问题会殃及池鱼,增长了定位故障问题的难度。一般采用多实例解决,一个实例一个业务库,互不干扰。
九、禁止在主库上执行后台管理和统计类的功能查询,这种复杂类的SQL会形成CPU的升高,进而会影响业务。
十、批量清洗数据,须要开发和DBA共同进行审查,应避开业务高峰期时段执行,并在执行过程当中观察服务状态。
十一、促销活动等应提早与DBA当面沟通,进行流量评估,好比提早一周增长机器内存或扩展架构,防止DB出现性能瓶颈。
十二、禁止在线上作数据库压力测试。
1三、禁止在数据库中存储明文密码。
1四、使用InnoDB存储引擎。
1五、表字符集统一使用UTF8。
1六、全部表和字段都须要添加中文注释。
1七、不在数据库中存储图片、文件等大数据。
1八、避免使用存储过程、视图、触发器、事件。
MySQL是OLTP应用,最擅长简单的增、删、改、查操做,但对逻辑计算分析类的应用,并不适合,因此这部分的需求最好经过程序上实现。
1九、避免使用外键,外键用来保护参照完整性,可在业务端实现。
20、对事务一致性要求不高的业务,如日志表等,优先选择存入MongoDB。
2一、表必须有主键,例如自增主键。
2二、禁止使用分区表。
2三、用DECIMAL代替FLOAT和DOUBLE存储精确浮点数。
浮点数的缺点是会引发精度问题,请看下面一个例子:
mysql> CREATE TABLE t3 (c1 float(10,2),c2 decimal(10,2)); Query OK, 0 rows affected (0.05 sec) >mysql> insert into t3 values (999998.02, 999998.02); Query OK, 1 row affected (0.01 sec) >mysql> select * from t3; +-----------+-----------+ | c1 | c2 | +-----------+-----------+ | 999998.00 | 999998.02 | +-----------+-----------+ 1 row in set (0.00 sec)
能够看到c1列的值由999998.02变成了999998.00,这就是float浮点数类型的不精确性形成的。所以对货币等对精度敏感的数据,应该用定点数表示或存储。
2四、使用TINYINT来代替ENUM类型。
2五、字段长度尽可能按实际须要进行分配,不要随意分配一个很大的容量。
选择字段的通常原则是保小不保大,能用占用字节少的字段就不用大字段。好比主键,强烈建议用int整型,不用uuid,为何?省空间啊。空间是什么?空间就是效率!按4个字节和按32个字节定位一条记录,谁快谁慢太明显了。涉及几个表作join时,效果就更明显了。更小的字段类型占用的内存就更少,占用的磁盘空间和磁盘I/O也会更少,并且还会占用更少的带宽。
有很多开发人员在设计表字段时,只要是针对数值类型的所有用int,但这不必定合适,就好比用户的年龄,通常来讲,年龄大都在1~100岁之间,长度只有3,那么用int就不适合了,能够用tinyint代替。又好比用户在线状态,0表示离线、1表示在线、2表示离开、3表示忙碌、4表示隐身等,其实相似这样的状况,用int都是没有必要的,浪费空间,采用tinyint彻底能够知足须要,int占用的是4字节,而tinyint才占用1个字节。
int整型有符号(signed)最大值是2147483647,而无符号(unsigned)最大值是4294967295,若是你的需求没有存储负数,那么建议改为有符号(unsigned),能够增长int存储范围。
int(10)和int(1)没有什么区别,10和1仅是宽度而已,在设置了zerofill扩展属性的时候有用,例:
root@localhost(test)10:39>create table test(id int(10) zerofill,id2 int(1)); Query OK, 0 rows affected (0.13 sec) root@localhost(test)10:39>insert into test values(1,1); Query OK, 1 row affected (0.04 sec) root@localhost(test)10:56>insert into test values(1000000000,1000000000); Query OK, 1 row affected (0.05 sec) root@localhost(test)10:56>select * from test; +------------+------------+ | id | id2 | +------------+------------+ | 0000000001 | 1 | | 1000000000 | 1000000000 | +------------+------------+ 2 rows in set (0.01 sec)
2六、字段定义为NOT NULL要提供默认值。
从应用层角度来看,能够减小程序判断代码,好比你要查询一条记录,若是没默认值,你是否是得先判断该字段对应变量是否被设置,若是没有,你得经过java把该变量置为''或者0,若是设了默认值,判断条件可直接略过。
NULL值很难进行查询优化,它会使索引统计更加复杂,还须要MySQL内部进行特殊处理。
2七、尽量不使用TEXT、BLOB类型。
2八、索引不是越多越好,按实际须要进行建立。
2九、查询的字段必须建立索引。
30、不在索引列进行数学运算和函数运算。
没法使用索引,致使全表扫描。
例:SELECT * FROM t WHERE YEAR(d) >= 2016;
因为MySQL不像Oracle那样支持函数索引,即便d字段有索引,也会直接全表扫描。
应改成----->SELECT * FROM t WHERE d >= '2016-01-01';
3一、不在低基数列上创建索引,例如‘性别’。
有时候,进行全表浏览要比必须读取索引和数据表更快,尤为是当索引包含的是平均分布的数据集是更是如此。对此典型的例子是性别,它有两个均匀分布的值(男和女)。经过性别须要读取大概一半的行。在种状况下进行全表扫描浏览要更快。
3二、不使用%前导的查询,如like ‘%xxx’。
没法使用索引,致使全表扫描。
低效查询 SELECT * FROM t WHERE name LIKE '%de%'; -----> 高效查询 SELECT * FROM t WHERE name LIKE 'de%';
3三、不使用反向查询,如 not in / not like。
没法使用索引,致使全表扫描。
3四、避免冗余或重复索引。
联合索引IX_a_b_c(a,b,c) 至关于 (a) 、(a,b) 、(a,b,c),那么索引 (a) 、(a,b) 就是多余的。
*3五、不使用SELECT ,只获取必要的字段。**
消耗CPU和IO、消耗网络带宽;
没法使用覆盖索引。
3六、用IN来替换OR。
低效查询 SELECT * FROM t WHERE LOC_ID = 10 OR LOC_ID = 20 OR LOC_ID = 30; -----> 高效查询 SELECT * FROM t WHERE LOC_IN IN (10,20,30);
3七、避免数据类型不一致。
SELECT * FROM t WHERE id = '19'; -----> SELECT * FROM t WHERE id = 19;
3八、减小与数据库的交互次数。
INSERT INTO t (id, name) VALUES(1,'Bea'); INSERT INTO t (id, name) VALUES(2,'Belle'); INSERT INTO t (id, name) VALUES(3,'Bernice'); -----> INSERT INTO t (id, name) VALUES(1,'Bea'), (2,'Belle'),(3,'Bernice'); Update … where id in (1,2,3,4); Alter table tbl_name add column col1, add column col2;
3九、拒绝大SQL,拆分红小SQL。
低效查询 SELECT * FROM tag JOIN tag_post ON tag_post.tag_id = tag.id JOIN post ON tag_post.post_id = post.id WHERE tag.tag = 'mysql'; 能够分解成下面这些查询来代替 -----> 高效查询 SELECT * FROM tag WHERE tag = 'mysql' SELECT * FROM tag_post WHERE tag_id = 1234 SELECT * FROM post WHERE post_id in (123, 456, 567, 9098, 8904);
40、禁止使用order by rand()
SELECT * FROM t1 WHERE 1=1 ORDER BY RAND() LIMIT 4; ----> SELECT * FROM t1 WHERE id >= CEIL(RAND()*1000) LIMIT 4;