Mysql开发规范(参考阿里巴巴规范手册)
1. 库名、表名、字段名必须使用小写字母,并采用下划线分割
2. boolean类型的判断字段使用 is_? 格式命名,比如是否删除 is_delete
3. 尽量不要使用char,使用varchar,因为varchar可以自己控制长度
4. 使用innerDB存储引擎(默认的),innerDB支持事物,并且默认使用行锁,提供了并发的性能
5. 表的字段名禁止使用Mysql默认的保留字,比如status,type
6. 字段定义成不能为null,null存储的时候是要额外消耗空间的,索引列为null值不走索引
这个规范个人感觉比较重要,因为在开发中有些字段定义为null时会出现各种让你意外的bug,比如一个金额字段,
查询返回使用基本数据类型的包装类,当出现null值容易出现空指针异常
7. 表必须有主键,并且提供主键自增,主键索引
8. 禁止使用存储过程,因为存储过程极难维护,一旦量太大了就是给后人留坑,不如把逻辑写在代码里面
Mysql索引建立原则
1. 不建不必要的索引,索引建立在where,join,order by,group by 指定的字段,比如:
select a.name --> 查询展示的字段不建议建立索引 from a left join b on a.id = b.a_id --> on条件后的关联字段建议建立索引 where a.id = 1 --> where条件后的字段建议建立索引 order by b.a_id --> order by 排序的字段建议建立索引
2. 一个表不要建过多的索引,阿里巴巴开发手册建议不超过6个
为表中字段建立索引是需要额外的时间以及空间的, 虽然索引能大大提高查询效率, 不过会加大insert, update等 操作的开销所以为一个表建立多个索引时, 最好选择业务上查询多, 新增修改操作少的表3. 为业务上确定唯一的字段建立唯一索引
一方面, 为业务上唯一(比如订单号)的字段建立唯一索引,能避免脏数据的产生, 而一旦出现了重复值时能很快的根据错误日志定位到问题
4. 禁止冗余索引
比如建立了如下两个索引: (a,b,c), (a,b), 这时其实第二个索引是完全没必要建立的, 因为索引(a,b,c)就包含了索引(a,b),建立第二个索引额外增加数据库开销 这里可以顺便说一下数据库建立组合索引时的最左原则, 比如建立了组合索引(a,b,c), 那么这个索引其实可以分成三个有效索引(a), (a,b), (a,b,c) 意思我在where a列, a列 and b列, a列 and b列 and c列时, 索引都有效
5. 不在低基数列上建立索引
比如字段is_delete, 该字段描述的一共就两个值0或1, 建立该索引相对于不建立索引的全表扫描没有任何优势, 而且增大了io负担
6. 合理使用覆盖索引
这是什么意思呢, 比如一条sql语句: select name, age from user where name = ? 我为name字段建立索引, 很明显能加快查询速度, 那么有什么办法能更快的查询呢? 这里就用到覆盖索引: 为name,age 两个字段建立索引, 那么查询到这条数据时, 因为索引包含了select语句查询的两列数据, 就不需要再根据索引去数据库取数据,而是直接返回索引就完成了数据返回
SQL语句优化
1. 禁止使用select * ,只 select自己需要的字段
2. 尽可能避免使用in,or,like全模糊匹配('%%'),like左模糊匹配('%?')
注意: 在我使用explain关键字分析查询语句的时候发现, in和or在字段少的情况下是会走索引的, 只有在in(1,2,3......)或or...上千个的时候不走索引, 所以具体使用看业务而定. 而like全模糊和左模糊是完全不会走索引查询的
3. 当只需要查询指定多少条数据时,使用limit,比如 select id from a limit 10,查询a表id十条数据
4. insert使用批量添加 ,减少与数据库的交互
5. 业务上大的事物拆分成多个小的事物,缩短锁的持续时间
事物A: update a set status = 1 where id = 1 update a set status = 1 where id = 2 update b set status = 1 where id = 1 update b set status = 1 where id = 2 在事物A执行的时候, 意味着a表id = 1, 2的行, b表id = 1, 2的行都被行锁锁定了, 只有在事物A执行完成之后, 才会释放锁.
如果把事物A拆分成两个事物: 事物B: update a set status = 1 where id = 1 update a set status = 1 where id = 2 事物C: update b set status = 1 where id = 1 update b set status = 1 where id = 2 那么在B事物执行完之后,a表的id = 1, 2的行锁被释放, 然后再执行事物C
6. 学会使用explain分析自己的sql语句点击打开链接
7. 优化大的分页
比如我order表中有100万条数据,我需要查询第90万数据的后20条: select * from order limit 900000, 20 mysql内部需要查询到所有数据, 然后从900000条开始截取后面20条显示, 这样的查询效率是很低的, 如何优化? 执行 select id from order limit 900000, 20 因为id有索引, 所以很快能查询到所需要的20条数据的id 执行 select * from order t1 left join (select id from order limit 900000, 20) t2 on t1.id = t2.id 这样, 就能很快的查询到该20条数据了
数据库优化
1. 读写分离: 通过配置读写分离,一个库负责读,一个库负责写,降低数据库压力. 读写分离大佬博客
2. 分库分表
分库: 顾名思义, 就是把一个表的数据分成多个数据库存储, 比如我有订单表order数据1000万, 查询起来很慢 那么可以把订单存储在不同的数据库中, 可以根据order表中指定字段,进行取模存入不同的数据库中. 假如订单表中有user_id的字段, 要把1000万数据分两个库存储,可以用user_id % 2 , 结果为0的存入一 个库,不为0的存入另一个库 分表: 水平分表: 将数据库表中的数据分散到多表中存储,主要解决表行数过大的问题. 一个很大的表,分割之后降低了读的数据以及索引的页数,提高查询速度. 缺点是查询时需要多个表名,查询所有的数据需要union 垂直分表: 将数据库中的一个字段很多的表横中切割,把比较重要的字段分在一个表中, 其他的分散在另外一个表中存储,垂直分表使数据行变小,减少查询的io次数. 缺点是查询整个表的数据时需要join
3. 优化内核(DBA的事)