经过多次迭代后,带有gpar的Groovy应用程序变慢

时间:2016-04-07 14:15:12

标签: mysql multithreading performance groovy gpars

我正在使用gpars并行处理250M行的MySQL数据库表。我创建了8个gpars线程,8个独立的数据库连接,并以这样的方式划分数据,即每个线程在不同的行范围内独立运行......这是一种廉价的MapReduce概念。核心是,逻辑是这样的:

  withExistingPool(pool)
  {
    connection_array.collectParallel()         
    {
       // Figure out which connection this thread can use. 
       // We use the index into the array to figure out 
       // which thread we are, and this tells us where to
       // read data.

       int i
       for (i = 0; i < connection_array.size(); i++)
          if (it == connection_array[i])
             break

       // Each thread runs the same query, with LIMIT controlling 
       // the position of rows it will read...if we have 8 threads
       // reading 40000 rows per call to this routine, each thread
       // reads 5000 rows (thread-0 reads rows 0-4999, thread-1 reads 
       // 5000-9999 and so forth). 

       def startrow = lastrow + (i * MAX_ROWS)
       def rows = it.rows( "SELECT * ... LIMIT ($startrow, $MAX_ROWS)")  

       // Add our rows to the result set we will return to the caller
       // (needs to be serialized since many threads can be here)

       lock.lock()
       if (!result) 
          result = rows
       else
          result += rows
       lock.unlock()
   }
 }

代码最初运行良好,启动时每秒超过10,000行。但在几百万行之后,它开始减速。当我们有2500万行而不是每秒10,000行时,我们每秒只能获得1,000行。如果我们终止应用程序并从我们停止的位置重新启动它,它会再次返回到每秒10K行,但是随着处理的继续,它总是会变慢。

有足够的处理能力 - 这是一个8路系统,数据库是通过网络进行的,因此无论如何都有相当长的等待时间。在运行时,处理器通常运行不超过25-30%。也似乎没有任何内存泄漏 - 我们监视内存统计信息,并且一旦处理正在进行中就看不到任何更改。 MySQL服务器似乎没有受到压力(它最初运行大约30%,随着应用程序减慢而减少)。

是否有任何技巧可以帮助这类事情在大量迭代中更加一致地运行?

2 个答案:

答案 0 :(得分:0)

好的,我们认为发现了这个问题 - 看起来它与在不同的线程上打开JDBC连接有关。通过最初在将要使用它的线程上打开连接,然后确保只有该线程访问该连接,性能问题就消失了。

我们还使用基于游标的方法重新编写逻辑,而不是使用LIMIT进行多次查询。有报道称,具有高start_row的LIMIT可能会很慢,但我们并没有看到通过进行此更改而产生的巨大差异(游标速度更快,但在处理行时性能仍然下降)。

但是,在这个和tim_yates建议的一些变化之间,我们运行速度比以前快了30% - 现在无论我们处理多少行,它都会一直很快。

答案 1 :(得分:0)

LIMITOFFSET效率不如大多数人想要的那么高。

执行LIMIT 1000,20时,将读取1000行,但会跳过,然后将读取和传送20行。也就是说,随着OFFSET的增长,查询变慢。

&#34;修复&#34;这是为了记住你离开的地方&#34;。使用AUTO_INCREMENT主键尤其如此,但可以使用任何PRIMARY KEYUNIQUE键完成此操作。

这是discussed further in my "Pagination" blog。它的目标是&#34; Next&#34;网页上的按钮,因此可以忽略一些讨论。