从硬件和软件方面入手
硬件:换固态,增大内存,调大缓冲区(当缓冲区大小为20-22GB时,性能较好)
软件:创建合适的索引、设置合理的数据库连接池、尽量批处理
针对硬件优化的原理是:
因为MySQL也是一个软件,数据的存储其实在磁盘上。而根据冯洛伊曼计算机的特性,任何程序只能先被加载到内存,才能运行。所以查询的过程也是将磁盘的数据先加载到内存,在后在内存中查找数据。但是机械硬盘的速度相对于固态硬盘比较慢。(这里就不多解释了,推荐《深入理解计算机系统》第六章)。内存增加,就可以设置更大的InnoDB缓冲区。如果缓冲区比较小,会导致查询的记录被加载到内存或者是被lru算法置换出内存,从而又需要从磁盘中把数据加载到内存(磁盘加载到内存的过程比较复杂,涉及到操作系统的知识,下次有时间单独写一篇)。这个过程比较耗时,也会频发发生。当调大缓冲区内存后,会让尽可能多的数据都在内存中,这样子就减少了页的换出,从而提高了效率。
针对软件
创建合适的索引
控制数据的大小,最好控制到百万级别,千万也行。然后就是执行的sql一定要走索引,要不然数据量大的话,会全表扫描。
全表扫描有两点非常耗时:
1.数据量大,假如100W数据,就需要根据sql的条件进行100W次判断。
2.全表扫描就需要把所有的记录都要加载到内存中,如果内存比较小的话,这里就会发生内存不够,需要lru将old链表中页置换到磁盘,然后将查询的记录以页(MySQL以16K为一页)为单位加到内存。这里old链表中的淘汰页置换要涉及到2次的磁盘操作,一直重复这个过程,直到全表数据被执行完。
所以如果创建一个合适的索引,就可以大大减少需要扫描的数据了。
设置合适的数据库连接池
数据库连接对象初始化的代价是昂贵的,所以会采用池化技术进行管理。 至于连接池到底该设置多大?个数通常设置为2*CPU核心数即可
可参考 数据库连接池到底应该设多大?
批处理
首先谈下事务,数据库事务的设置和提交都会耗费时间。这个过程包括确保对数据库的修改都已经完全保存到磁盘,检查数据库事务日志的一致性,等等。其次,数据库事务进行期间,通常事务都会对部分数据加锁,如果两个事物在同一个数据库行锁上发生竞争,应用的可扩展性就会受到影响。
因为事务的操作是昂贵的,所以我们的目标就是尽可能再一次事务中完成更多的操作。所以有时间将循环插入数据的操作变更为批量插入,其性能会大幅度提高。
参考书籍:
《深入理解计算机组系统》
《MySQL是怎样运行的 从根儿上理解MySQL》
《Java性能权威指南》第11章节
《MySQL技术内幕:InnoDB存储引擎》