总结一下工作中的MySQL调优经验

多数时候数据库会成为整个系统的瓶颈,比如大的数据量的插入与修改,频繁的亦或是高流量的访问,都会对数据库系统带来很大的压力。我在平时工作的时候,总是会遇到大数据量的插入、修改或是查询的操作,所以在工作的时候积累了一些MySQL数据库的调优方式,在这里与大家分享一下。

1、缓存。缓存是解决这类问题的一把手。它既可以加快整个系统(并非数据库系统,使用缓存的时候并没有去访问数据库)的访问速度,也可以减少数据库负载的压力。而缓存一般都是在查询中使用,我们并不希望每一次的查询都要去访问数据库。那么我们的缓存做到哪里呢?一般情况下版的系统都会存在服务层这一结构层次,而数据访问层一般都只是对于数据库的增删改查的接口的定义,所以我们的缓存就需要在服务层进行。而mybatis中的一级缓存,通过判断查询条件是否要访问数据库,查询条件与某一次相同,则直接返回缓存中的数据,查询条件不同则需要访问数据库,并且将结果放到缓存中。

2、当只需要一条数据时使用LIMIT 1.我们作为开发者,是能够知道我们需要的数据的条数的,若已经知道结果只有一条的时候,一定要使用limit 1 ,这样一来,MySQL在查询到一条数据之后,会立即停止搜索,这会带来性能上的提升。

3、避免select * ,取之所需。公司里的一些同事,无论查询什么都是直接select *,然后再从结果中取想要的字段。这样做的话,平白无故的给MySQL带来了不必要的负担,因为从数据库中读出越多的数据,查询就会变得越慢。所以,以后看到select * 的时候,想一下是否可以在这里进行一些优化。

4、为每张表设置一个id作为其主键。这个id最好是一个int类型的,推荐使用unsigned,并将其设置为自动增加auto_increment。之前就出现过一个同事将varchar的字段作为主键的情况, 然后在数据量较大的时候,数据库这个环节速度变得不是很友好,所以尽量不要使用varchar来当主键,它会使得性能出现下降。实际上,在mysql的innodb引擎中,表是根据主键的顺序,以索引(平衡树的结构,非二叉树)的形式存放的,也就是整张表变化了一个索引。所以再不加索引的情况下,通过主键查找数据比通过其他字段查找数据快。既然主键是索引,就需要去进行维护了。这个可能就需要在索引树某几个节点的中间插入数据,或者会牵扯到数据页的分裂,索引使用自增的int类型的主键,它是这一种追加的方式,就不会牵扯到往中间插入数据的这种情况,也不会有叶子结点的分裂。并且有些时候,int类型的长度比vachar小,普通索引里面会保存主键的数据,所以普通索引占据的空间更小。

5、使用enum而不是varchar。实际上,enum保存的是tinyint类型,但其显示为字符串。用这个字段来作一些选项列表就变得很合适了。比如你有一个字段,比如“性别”、“状态”或“所属部门”等,你知道这些字段的值是固定且有限的,那么可以考虑使用enum。对于性别这个字段,一般分为两种,有可能还有保密这种情况,我们可以使用数字1、2、3来分别表示这三张情况,而对于这些数字含义的区分则是业务层的事情了。我们需要将一些繁琐的需要计算的步骤全部放到业务层(或者说是服务层),因为系统的瓶颈在数据库,我们不能将过多的计算过程压到数据库上面去。数据库存储的数据应该尽量简单,但是,我们会在业务层结合具体的业务,对这些简单的数据进行分析。

6、尽可能的使用not null。除非你有一个很特别的原因要去使用null值,你应该总让你的字段保持为not null。

7、选择正确的存储引擎。myisam适合一些需要大量查询的应用。但其对于大量写操作并不是很好。因为它使用到的是表级锁,所以在你更新的时候,整张表都会被锁起来,试想一下,当你在更新某一行数据的时候,导致其他的行都无法被访问,这会不会  很难受呢。另外,myisam对于select count(*)这类操作的计算时很快的。而至于innodb而言,对于一些小的应用,它会比myisam还慢。它支持的是行级锁,于是写操作较多的时候,它会更加优秀。它还支持一些更高级的应用,比如说:事务。

8、建立合适的索引。上面说到了其实表的主键就是一种索引。如果某个字段你总要拿来做搜索条件的话,那么为它建立索引吧。这里的原理是,普通的字段建立了索引,索引树的子节点其实是主键,也就是说搜索的时候,先通过普通索引找到主键,再通过主键去查找表中的数据(这个过程叫做回表)。必要的时候,我们还可以建立覆盖索引,比如,需要通过身份证去查询姓名的这个查询很频繁,我们可以建立覆盖索引,也就是对身份证和姓名建立索引,如(idcard,name),这样的话,在索引树中不仅仅有对应的id,还有该行对应的name的值,此时就不需要根据id进行回表操作了。并且建立覆盖索引时需要注意一些原则,比如我现在数据库里只有一个主键索引,身份证姓名索引,此时我们还有一个查询——通过身份证查找地址,但是这个查询并不是很频繁,此时需不需要建立(idcard,address)这个覆盖索引呢?我们需要知道的是,建立索引是会占据表的磁盘空间的,并不是没有任何消耗的。其实这个是没必要的,因为建立了(idcard,name)这个覆盖索引之后,就不用再建立idcard这个索引了。建立覆盖索引需要注意索引的顺序,如果通过建立覆盖索引可以少维护一个索引的话,这个顺序可以优先考虑。另一个就是空间的问题了。比如(name,age)索引,name是比age要大的,索引可以考虑一个(name,age),一个(age)。还有一点需要知道:加了索引是会影响对于数据库写操作的性能的。原因是:数据库需要维护索引树的正确的状态,增加数据就会改变原来的结构,这个过程会带来性能的损耗。但是,不要以为建立索引,就可以为所欲为。其中有一些常用的规则需要去遵循以下的。详情请见这篇博客:建立索引常用的规则。

(未完待续)

你可能感兴趣的:(java)