Java Mysql大数据出堆空间

时间:2013-07-16 01:03:57

标签: java mysql heap heap-memory

我有一个应用程序可以从MySQL数据库访问大约200万条推文。具体来说,其中一个字段包含一条文本推文(最大长度为140个字符)。我正在将每条推文分成ngram的单词ngrams,其中1< = n< = 3.例如,考虑一下句子:

I am a boring sentence.

相应的nGrams是:

I
I am
I am a
am
am a
am a boring
a
a boring
a boring sentence
boring
boring sentence
sentence

有大约200万条推文,我正在生成大量数据。无论如何,我很惊讶从Java获得堆错误:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at com.mysql.jdbc.MysqlIO.nextRowFast(MysqlIO.java:2145)
    at com.mysql.jdbc.MysqlIO.nextRow(MysqlIO.java:1922)
    at com.mysql.jdbc.MysqlIO.readSingleRowSet(MysqlIO.java:3423)
    at com.mysql.jdbc.MysqlIO.getResultSet(MysqlIO.java:483)
    at com.mysql.jdbc.MysqlIO.readResultsForQueryOrUpdate(MysqlIO.java:3118)
    at com.mysql.jdbc.MysqlIO.readAllResults(MysqlIO.java:2288)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2709)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2728)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2678)
    at com.mysql.jdbc.StatementImpl.executeQuery(StatementImpl.java:1612)
    at twittertest.NGramFrequencyCounter.FreqCount(NGramFrequencyCounter.java:49)
    at twittertest.Global.main(Global.java:40)

以下是Netbeans的上述输出所给出的问题代码声明(第49行):

results = stmt.executeQuery("select * from tweets");

所以,如果我的内存不足,那一定是它试图立即返回所有结果然后将它们存储在内存中。解决这个问题的最佳方法是什么?具体来说,我有以下问题:

  1. 如何处理results而不是整套?
  2. 如何增加堆大小? (如果可能的话)
  3. 随意添加任何建议,如果您需要更多信息,请与我们联系。

    修改 而不是select * from tweets我将表格划分为大小相等的子集,大小约为总大小的10%。然后我尝试运行该程序。看起来它工作正常,但它最终给了我相同的堆错误。这对我来说很奇怪,因为我过去运行过相同的程序,成功发布了610,000条推文。现在我有大约2,000,000条推文或大约3倍的数据。因此,如果我将数据拆分为三分之一,它应该可以工作,但我更进一步将子集拆分为10%的大小。

    有些记忆没有被释放吗?以下是代码的其余部分:

              results = stmt.executeQuery("select COUNT(*) from tweets");
              int num_tweets = 0;
              if(results.next())
              {
                  num_tweets = results.getInt(1);
              }
              int num_intervals = 10;                  //split into equally sized subets
              int interval_size = num_tweets/num_intervals;
    
              for(int i = 0; i < num_intervals-1; i++)        //process 10% of the data at a time
              {
                results = stmt.executeQuery( String.format("select * from tweets limit %s, %s", i*interval_size, (i+1)*interval_size));
                while(results.next())  //for each row in the tweets database
                {
                    tweetID = results.getLong("tweet_id");
                    curTweet = results.getString("tweet");
                    int colPos = curTweet.indexOf(":");
                    curTweet = curTweet.substring(colPos + 1);                           //trim off the RT and retweeted 
                    if(curTweet != null)
                    {
                        curTweet = removeStopWords(curTweet);
                    }
    
                    if(curTweet == null)
                    {
                        continue;
                    }
                    reader = new StringReader(curTweet);
                    tokenizer = new StandardTokenizer(Version.LUCENE_36, reader);
                    //tokenizer = new StandardFilter(Version.LUCENE_36, tokenizer);
                    //Set stopSet = StopFilter.makeStopSet(Version.LUCENE_36, stopWords, true);
                    //tokenizer = new StopFilter(Version.LUCENE_36, tokenizer, stopSet);
                    tokenizer = new ShingleFilter(tokenizer, 2, 3);
    
                    charTermAttribute = tokenizer.addAttribute(CharTermAttribute.class);
    
                    while(tokenizer.incrementToken())                  //insert each nGram from each tweet into the DB
                    {
                        insertNGram.setInt(1, nGramID++);
                        insertNGram.setString(2, charTermAttribute.toString().toString());
                        insertNGram.setLong(3, tweetID);
                        insertNGram.executeUpdate();
                    }
                }
              }
    

3 个答案:

答案 0 :(得分:1)

您始终可以使用-Xmx参数增加JVM可用的堆大小。您应该阅读所有可用的旋钮(例如perm gen size)。 Google可提供其他选项或阅读this SO answer.

对于32位计算机,您可能无法解决此类问题。你需要64位和大量的RAM。

另一种选择是将其视为地图缩减问题。使用Hadoop和Mahout在集群上解决它。

答案 1 :(得分:1)

不要从表中获取所有行。尝试选择部分 通过设置查询限制,根据您的要求生成数据。您正在使用MySQL数据库,您的查询将从推文限制0,10中选择*。这里0是起始行id,10表示从开始起10行。

答案 2 :(得分:0)

您是否考虑过流式传输结果集?页面中间是结果集的一部分,它解决了你的问题(我想?)将n克写入文件,然后处理下一行?或者,我是否误解了你的问题? http://dev.mysql.com/doc/refman/5.0/en/connector-j-reference-implementation-notes.html