Java& Mysql处理海量数据

时间:2013-11-13 19:29:29

标签: java mysql large-data

我的问题是,我有两个数据库表,一个有大约10 000条记录,另一个有5 000 000条记录,每条记录有56列。现在我要做的是,将10 000的每条记录与另一张表中的每条记录进行比较,找到10条最佳记录(比较列值等)。 所以我想在合理的时间内找到一些想法,因为现在它需要我太长时间... 我一直在寻找互联网并发现hadoop,但是我从来没有使用它,我不确定它是否会在我的情况下完成工作...... 我的机器有2个核心和4gb ram,所以它不是公牛。 如果在合理的时间内甚至可行,那么感谢您的任何答案

3 个答案:

答案 0 :(得分:1)

hadoop的想法是它可以帮助您并行化代码执行。如果你只有一台机器我不认为hadoop适合你。由于您有2个内核,因此可以利用Java线程。

另一个限制因素是记忆。如果您可以将所有记录提取到内存中,则只需在开始计算之前执行此操作。如果不是这种情况(似乎db大小超过了你的RAM大小),一旦计算线程完成了一些记录,辅助线程就可以从数据库中获取额外的记录到内存中。下面是算法草图:

  • 两个工作线程并行工作(由于计算密集型任务,线程数= cpus数)
  • FirstArray =在数组或ArrayList中加载10.000,确保您没有使用并发结构。两个线程都将访问此数组,但不会改变它。 SecondArray将由DB Thread提供(第3-4点)。 FirstArray对于两个线程都是相同的,SecondArray会有所不同。你会有嵌套循环:

    for (elem1: FirstArray) {
        for (elem2: SecondArray){
             computeSmth(elem1, elem2)
             if (bestSoFar()) store()
        }
    }
    

一旦完成工作线程,就会向BlockingQueue询问下一部分数据 - 这是新的SecondArray。

  • DB Thread(实际上是第三个线程)将负责批量从数据库中获取数据并填充将由Worker Threads进一步处理的数组。
  • 假设第二个表中的400.000个元素适合内存。我们把它分成4个区域。
    • 1个区域将用于第一个线程正在处理的元素
    • 2区域将用于由第二个线程处理的元素,
    • 3 region是一个数组,等待BlockingQueue中的一个线程(容量为1),
    • 4将用于从数据库中提取的数据,但无法放入队列,因为其中一个工作线程未采用另一个数组。这基本上意味着 数据库线程将阻塞,直到某个线程从队列中获取下一个数组,这意味着它已完成前一个数组,之前的数组可能是GCed,这意味着 你不会用完内存。
  • 队列大小可能是根据最大MySQL批量大小,MySQL检索时间和工作线程一次批处理所花费的时间进行调整的主题。
  • 应该充分考虑bestSoFar()的逻辑以最小化线程同步。
  • 基本上算法应该很好地扩展(每个CPU可以提供接近线性的改进)。

答案 1 :(得分:0)

有十几种方法可以做到这一点。这取决于您需要比较的内容。

从两个表中选择对最重要列具有相同值的行的方法。比对两个表中的每个匹配行进行比较。

但是,如果匹配是直接forware(列匹配或不匹配),我会写一个好的SQL查询,返回每个行组合的匹配列数,并选择前10:)。

我认为,最佳策略是逐步处理10.000行并尝试使用查询找到最匹配的行,并在java中进行附加计算以对最佳行进行排序。

理想情况下,我会为它编写一个MapReduce作业。但如果您还没有设置它,那么硬编程是您最好的选择。

答案 2 :(得分:0)

500万x 57双打就像2 GB RAM一样。

您的4 GB不应该是一个问题。

为了加快速度,请使用索引。也许你也可以实现自己的索引。

或在适当情况下使用排序