前几天为一个保险公司做一个咨诉系统,其中有个功能是统计报表。要求是这个报表在mysql中跑要两秒以内查询出结果,在系统之中查询要在七八秒之内,而数据量也会在百万级别以上。
本身mysql的查询性能就稍微差一些,而且mysql连表查询的效率更是差强人意。由于开始的表的设计原因,有些统计数据要在连表中来查询,而且要求的时间期限是一年以内的数据。
开始写了一个逻辑的sql,一旦数据量超过一万,那速度简直是老牛拉磨一般,后来加上索引,又对不必要的逻辑进行优化,还是很慢。
后来发现好多的索引并没有走,原因有几个:
1、连表子查询的字段对应的格式不同,有的是int类型,有的是varchar类型。
2、连表子查询的两个表的varchar字符集居然不同,新的表示utf-8mb4的,而老的表示utf-8的。这就导致连表查询的时候回现将utf-8的字符集挨个转换为utf-8mb4,然后在进行查询,这速度简直是老牛拉磨一般。没办法只能每次查询之前现将字符集转换为utf-8。发现速度相差十倍不止。
3、时间格式不同也会导致不走索引,当时间格式为date类型或者datetime类型的时候,要注意转换一下。
虽然速度要比原来快好几十倍,但是当数据量达到百万数据量,特别是连表子查询中其他的表数据量达到几百万的时候,依然是非常的慢。原因有两个:
1、因为要和一年以内的时间比对计算重复率,所以当用到函数DATE_SUB(时间字段, INTERVAL 1 DAY)的时候,明显速度被拖慢。
2、因为要做翻页,所以要先计算count值,这个也会被拖慢。
如何优化这两个问题呢?看来还得研究一下。
—————————————————分割线———————————
前几天一直在做webService接口,这几天断断续续有开始研究之前那个报表查询效率问题。因为查询效率没法达到甲方的要求,所以尝试了一种解决方案,就是做一个定时任务,每天晚上跑报表里面前一年的数据,将计算结果存到一个新表里面,然后在使用的时候连表查询,这样就避免了复杂的逻辑查询拖慢查询速度。
但是实际上定时任务批处理效率居然非常高,而抛开了复杂查询的报表依然还是很慢,不知道是因为优化的方向不对还是说已经没有余地可以再进行优化,只能更改功能实现方式或者需求。
今天是17-8-20,再次做个记录。