通过java中的多个线程从数据库中读取

时间:2017-01-28 22:12:14

标签: java multithreading

我正在使用java中的多个线程从vertica数据库中读取数据。 我有大约2000万条记录,我打开5个不同的线程,有这样的选择查询....

import java.util.Scanner; 

public class PigConverter
{ 
public static void main(String[] args) 
    { 
Scanner anscay = new Scanner(System.in);
System.out.print("Enter a word:"); 
String word = anscay.nextLine(); 
System.out.println("This word, in pig latin, would be:");

String pigConvert;
 for (int i=0; i < word.length(); i++)
        {
       if(word.charAt(i)=='a' || word.charAt(i)=='e' || word.charAt(i)=='i' ||
           word.charAt(i)=='o' || word.charAt(i)=='u') 
            {
              String second = word.substring(0,i);
              String first = word.substring(i,word.length());
              System.out.println(first+second+"ay");    
            }

        }
    }
}

上面的查询分配20K个不同的记录,从db读取到每个线程。 例如,第一个线程将首先读取20k记录,然后从100000个位置开始读取20K记录等等

但我没有得到性能提升。事实上,如果需要x秒来读取2000万条记录,则使用单个线程,然后每个线程从数据库中读取几乎需要x秒。 不能从x秒开始有一些改进(期待x / 5秒)?

任何人都可以查明出了什么问题吗?

3 个答案:

答案 0 :(得分:2)

除了你理解多线程可以改善哪些情况以及哪些情况可能没有改善之外,没有什么会出错。

您的数据库可能位于磁盘上;这是一个带有一组磁头的磁盘,它们都是一致的,所以它就像是一个单头的磁盘一样。头部需要时间从一个位置移动到另一个位置;这被称为寻求时间

当您从一个线程读取顺序数据时,磁头必须从一个磁道移动到另一个磁道。

当您从多个线程中读取不同的顺序数据流时,磁头必须移动很多,才能从一个轨道跳到另一个轨道,这个轨道很远,然后再回到第一个轨道。这有很多寻求开销。

当然,您的硬盘使用单根电缆连接到您的主板,因此所有数据(在所有搜索开销之后)必须通过它才能被不同的线程处理。

结果当然是非常糟糕的表现。

带回家的教训是:

  

多线程永远无法改善来自同一设备的大量I / O.

换句话说:当所有数据来自单个顺序源时,处理数据的并行性决不会提高性能。

如果您在5个不同的磁盘上存储了5个不同的数据库,那么效果会更好。 (如果您还将这些磁盘连接到主板上的5个独立IDE控制器,那将会更好。)

答案 1 :(得分:1)

我不会重复Mike Nakis的说法,因为它是真的并且得到了很好的解释:

  

多线程无法改善物理磁盘的I / O

然而,我想补充一些内容。

执行类似的查询时:

 select * from tableName order by colname limit 20000 offset start*20000.

从客户端,您可以处理可以通过使用多个线程来改进的查询结果。

但是从数据库方面来说,您还没有处理查询,而Vertica数据库可能是根据机器的可能性执行并行任务来执行查询的。

因此,从客户端,您可以在一个,两个或三个并行线程中分离查询的执行,最终不应该更改很多东西,因为专业数据库旨在根据请求的数量优化响应时间收到并加工机会。

答案 2 :(得分:0)

不,你不应该得到x / 5秒。你没有想到你在相同的时间内获得5倍的记录数。它关乎吞吐量,而不是时间。