最近系统出了一点问题。在客户那边,因为系统的用户规模的变大,历史数据变得特别大。十来天的数据就有上千万了。系统本身就是一个准实时系统,响应要求较高。但是有个数据库操作却需要化4分钟多。客户没法接受了。这个操作是通过一个存储过程来做的。模拟了一个环境,测试了一下,发现是其中的一个查询特别费时。
语句很简单:select count(*) into @totalCount from A where ( condition1 or conditon2) and condition3 and condition4
表A的数量大概是一千五百万,查询语句的结果是6000多。查了查,该有的索引都有了。
用的是MySQL的InnoDB。对于InnoDB来说,上千万的数据确实是多了。需要从SQL语句本身来优化确实很不容易了。但是这个语句的问题也很明星,条件or很扎眼。肯定有问题。改一下:
select count(*) into @a from A where condition1 and condition3 and condition4;
select count(*) into @a from A condition2 and condition3 and condition4;
set @totalCount=@a+@b;
效果很明显,只需5秒多就出来了。
有时使用几个简单的语句可能比复杂的一条语句更有效。这个当然得看数据库。最好是测试一些。
在这种还想起了MySQL一个让很多人头疼的问题:就是count的速度问题。当count的数据量很大时,InnoDB的速度确实很不敢恭维。在数据库端确实也没有什么特别好的解决方法。既然在数据库端没法解决,那能不能在应用端解决呢。因为MySQL对SQL语句的执行是单CPU的,而现在机器都有多颗CPU,能不能把count语句按一定的条件分成多个语句进行并发查询,然后再把结果相加呢。Java自1.5版本加了concurrent包之后,对于并发编程已经是相当简单了。可以试试。当然在实际应用中还要考虑另一个问题:数据库连接数的问题,并发查询语句多了,连接数自己就增加了。有没有效果,还得看具体应用。