这几天都在看一个性能调优的存储过程,该存储过程在客户生产环境(数据库为mysql 5.1 )的运行时间为30到40多分钟,客户的要求是提高50%以上。
该存储过程的实现:
- 两个表的查询(由于业务需要,还涉及到该表的子查询),分别插入到临时表;两个表的数据分别为310W+,120W+
2. 中间还需要做一些处理,将临时表的数据group by插入到另一个临时表;
- 最后将临时表的数据group by插入到一张正式表,插入的数据140W+
接着这几天就在优化性能的路上越走越远,尝尽了各种方法,也尝到了各种苦头。
各种各样的尝试:
一、我感觉这实现的逻辑有点复杂,然后按照我的想法把实现简化了。然而性能并没有得到改善。因为我的实现是把大数据量提到了前面,而后面的操作还得争对这部分大数据量进行操作,比如group by。所以虽然我的实现在逻辑上简化了,但是性能并没有提升。
二、根据不同的逻辑标识,创建了两套临时表,这样一张表的数据量就不会那么大,希望给后面的操作减少些压力。还是以失败告终。原因是因为逻辑标识的设置,所有都是走的一套逻辑,第二套逻辑根本就只是走过过场,不会真正去查那百万数据的表,所以压力还是在那300多万的表。
三、使用预处理语句。其实对预处理语句的机制不是太明白,只是听说预处理的效率更高。性能还是没提升,大概是因为并没有太多相似的查询或插入吧。嗯,不是太明白预处理机制。
四、将子查询拿掉,先用临时表保存这部分数据。这样那300多万数据的表还是得查两次,没啥性能提升。
五、将临时表的引擎由myisam改为memory,数据库的全局变量max_heap_table_size,tmp_table_size也设置为了1000M,同生产环境。结果还是报The table 'tmp_item_bu_parter_price' is full,所以说数据量太大,导致内存撑爆?
六、也是在逻辑上走不同分支,结果发现走的都是同一个逻辑。这个有点亏,之前在这方面考虑的时间也挺长,没有先去查明客户的设置。
七、多线程。由于存储过程中使用了insert into ...select...的句式,而且where条件未中索引,所以造成了全表锁。而多线程的测试结果无疑就是锁表了,有些数据执行失败。
八、在逻辑上不以全量的方式插入,而是增量,可是那些已存在的数据还是得更新啊。所以性能应该差不多。