java 处理千万数据经验杂谈
2010-09-25 23:03
183 查看
最近做了两个关于大数据量的处理任务。这里谈一谈经验。
首先java程序端需要保证质量。
千万数据的处理我首先想到分页,主要是担心一次性load所有数据会撑爆内存。于是会使用oracle中的rownum和mysql中的limit进行分页。实践证明,分页不仅不是内存性能提高的必要手段,还是影响程序时间性能的罪魁祸首。首先谈空间性能j。dbc的ResultSet是采用next迭代子模式来迭代结果集的。理论上应该是数据库游标这样的按需索取的方式。这在oracle中已经实现了,在mysql中默认情况下是不能实现的,需要修改statement运行参数才可以。我们可以在做方案之前做个小实验然后用profile工具论证这个事实。其次谈时间性能。如果使用了分页,数据库的执行计划其实是首先做一次全表查询,然后在这个查询的基础上取出该页的数据,效率极低。这个论证起来其实很简单,只要利用数据库的解释执行计划的功能即可。oracle中我记得是explain语句,mysql下是explain或describe。
那么java端的内存空间问题会发生在哪里呢?会发生在你缓存了多少数据。拿个最简单的例子,你需要把数据库的一张表的所有数据写入磁盘中。最极端的方式是load所有记录到内存中再一次性dump到磁盘里或者读一条记录写一条记录。前者的时间性能高空间性能低,后者的空间性能高时间性能低。这里体现的是内存和io操作的矛盾。这是计算机工程中最经典的一对矛盾:时间和空间。如何处理这对矛盾只能具体问题具体分析了。
java端的质量保证了,现在来看看数据库的设计和优化。由于是千万级数据,所以往往设计上牵一发动全身。主要的原则是 一 尽量多用索引 二对数据进行预处理。比如刚才的例子-分页。假如应用真的有分页功能,在条件的允许下,我们可以使用表格的id作为条件来分页而不是使用数据库本身的分页语句机制。原因很简单,无论是oracle的rownum还是mysql的limit都不提供索引功能。而id是具有索引功能的,从这个切入点出发去分页效率往往会很高。但这里的前提是条件允许。某些应用场景下是适合利用id做分页的。比如用户的id是离散的,这样利用id做分页的时候条件语句不好写。诸如此类。预处理是另外一种提升性能的方法。中心思想是磨刀不误砍柴功。有时候,有规律的数据可以降低程序中的IO数量。
总结一下,写java程序处理大规模数据的时候一定要考虑数据库的设计是否符合应用场景,sql语句是否高效,程序的io操作是否精简,程序的内存空间是否会out of memory。以上几个问题都是千万数据处理中可以优化的点。记住,优化往往是一种反工程的行为,越优化的代码,你的应用场景就越窄。所以千万不要抱着鱼和熊掌兼得的思想去写程序。
首先java程序端需要保证质量。
千万数据的处理我首先想到分页,主要是担心一次性load所有数据会撑爆内存。于是会使用oracle中的rownum和mysql中的limit进行分页。实践证明,分页不仅不是内存性能提高的必要手段,还是影响程序时间性能的罪魁祸首。首先谈空间性能j。dbc的ResultSet是采用next迭代子模式来迭代结果集的。理论上应该是数据库游标这样的按需索取的方式。这在oracle中已经实现了,在mysql中默认情况下是不能实现的,需要修改statement运行参数才可以。我们可以在做方案之前做个小实验然后用profile工具论证这个事实。其次谈时间性能。如果使用了分页,数据库的执行计划其实是首先做一次全表查询,然后在这个查询的基础上取出该页的数据,效率极低。这个论证起来其实很简单,只要利用数据库的解释执行计划的功能即可。oracle中我记得是explain语句,mysql下是explain或describe。
那么java端的内存空间问题会发生在哪里呢?会发生在你缓存了多少数据。拿个最简单的例子,你需要把数据库的一张表的所有数据写入磁盘中。最极端的方式是load所有记录到内存中再一次性dump到磁盘里或者读一条记录写一条记录。前者的时间性能高空间性能低,后者的空间性能高时间性能低。这里体现的是内存和io操作的矛盾。这是计算机工程中最经典的一对矛盾:时间和空间。如何处理这对矛盾只能具体问题具体分析了。
java端的质量保证了,现在来看看数据库的设计和优化。由于是千万级数据,所以往往设计上牵一发动全身。主要的原则是 一 尽量多用索引 二对数据进行预处理。比如刚才的例子-分页。假如应用真的有分页功能,在条件的允许下,我们可以使用表格的id作为条件来分页而不是使用数据库本身的分页语句机制。原因很简单,无论是oracle的rownum还是mysql的limit都不提供索引功能。而id是具有索引功能的,从这个切入点出发去分页效率往往会很高。但这里的前提是条件允许。某些应用场景下是适合利用id做分页的。比如用户的id是离散的,这样利用id做分页的时候条件语句不好写。诸如此类。预处理是另外一种提升性能的方法。中心思想是磨刀不误砍柴功。有时候,有规律的数据可以降低程序中的IO数量。
总结一下,写java程序处理大规模数据的时候一定要考虑数据库的设计是否符合应用场景,sql语句是否高效,程序的io操作是否精简,程序的内存空间是否会out of memory。以上几个问题都是千万数据处理中可以优化的点。记住,优化往往是一种反工程的行为,越优化的代码,你的应用场景就越窄。所以千万不要抱着鱼和熊掌兼得的思想去写程序。
相关文章推荐
- java数据可视化--圆柱体乱码处理
- 数据序列化处理之经验积累(3) -- ObjectStateFormatter
- 数据处理----Java数据处理之RMI
- elasticsearch__3__java操作之Facets 数据分组统计处理
- java千万级别数据生成文件思路和优化
- android( java) 处理 null 和 预防空指针异常(NullPointerException) 的一些经验。
- Java如何处理多线程的数据同步问题
- JAVA大集合数据分批次进行切割处理
- Java字节流数据逐行读取(readLine),处理以Tab分隔符划分的数据
- 编程经验系列-Java学习杂谈(十)--Struts2
- java中对数据进行处理
- Java异常处理的误区和经验总结
- Apache HttpComponents 的使用入门(java使用HttpClient访问Api, 使用json.org库处理json数据)
- java海量大文件数据处理方式
- java千万级别数据生成文件思路和优化
- Java 异常处理的误区和经验总结
- JAVA并发处理经验(四)并行模式与算法1:生产者消费与单例模式
- java大数据处理-大量数据到Excel
- java处理超过65536行数据
- 161124、Java 异常处理的误区和经验总结