Mysql性能优化以及开发规范

Mysql开发规范(参考阿里巴巴规范手册)

1. 库名、表名、字段名必须使用小写字母,并采用下划线分割

2. boolean类型的判断字段使用 is_? 格式命名比如是否删除  is_delete 

3. 尽量不要使用char使用varchar,因为varchar可以自己控制长度

4. 使用innerDB存储引擎(默认的),innerDB支持事物,并且默认使用行锁,提供了并发的性能

5. 表的字段名禁止使用Mysql默认的保留字,比如status,type

6. 字段定义成不能为nullnull存储的时候是要额外消耗空间的,索引列为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. 尽可能避免使用inorlike全模糊匹配('%%')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的事)

猜你喜欢

转载自blog.csdn.net/lp2388163/article/details/80762726