当前位置: 首页 > 面试题库 >

如何并行而不是顺序执行多个查询?

白星渊
2023-03-14
问题内容

我要查询所有10个表以从中获取用户ID,并将所有用户ID加载到HashSet中,以便可以拥有唯一的用户ID。

截至目前,它是按顺序进行的。我们转到一个表,并从中提取所有user_id并将其加载到哈希集中,然后将其存储在第二个和第三个表中并继续运行。

    private Set<String> getRandomUsers() {
        Set<String> userList = new HashSet<String>();

        // is there any way to make this parallel?
        for (int table = 0; table < 10; table++) {
            String sql = "select * from testkeyspace.test_table_" + table + ";";

            try {
                SimpleStatement query = new SimpleStatement(sql);
                query.setConsistencyLevel(ConsistencyLevel.QUORUM);
                ResultSet res = session.execute(query);

                Iterator<Row> rows = res.iterator();
                while (rows.hasNext()) {
                    Row r = rows.next();

                    String user_id = r.getString("user_id");
                    userList.add(user_id);
                }
            } catch (Exception e) {
                System.out.println("error= " + ExceptionUtils.getStackTrace(e));
            }
        }

        return userList;
    }

有什么方法可以使这个多线程的,以便他们为每个表并行地从我的表中获取数据?最后,我需要userList哈希集,该哈希集应具有所有10个表中的所有唯一用户ID。

我正在使用Cassandra数据库,并且连接仅建立一次,因此不需要创建多个连接。


问题答案:

如果您能够使用Java
8,则可以parallelStream对表列表进行操作,并使用lambda将表名扩展为每个表的唯一ID对应列表,然后将结果合并为一个表哈希。

没有Java 8,我将使用Google Guava的可监听期货和类似以下内容的执行服务:

public static Set<String> fetchFromTable(int table) {
    String sql = "html" target="_blank">select * from testkeyspace.test_table_" + table + ";";
    Set<String> result = new HashSet<String>();
    // populate result with your SQL statements
    // ...
    return result;
}

public static Set<String> fetchFromAllTables() throws InterruptedException, ExecutionException {
    // Create a ListeningExecutorService (Guava) by wrapping a 
    // normal ExecutorService (Java) 
    ListeningExecutorService executor = 
            MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());

    List<ListenableFuture<Set<String>>> list = 
            new ArrayList<ListenableFuture<Set<String>>>(); 
    // For each table, create an independent thread that will 
    // query just that table and return a set of user IDs from it
    for (int i = 0; i < 10; i++) {
        final int table = i;
        ListenableFuture<Set<String>> future = executor.submit(new Callable<Set<String>>() {
            public Set<String> call() throws Exception {
                return fetchFromTable(table);
            }
        });
        // Add the future to the list
        list.add(future);
    }
    // We want to know when ALL the threads have completed, 
    // so we use a Guava function to turn a list of ListenableFutures
    // into a single ListenableFuture
    ListenableFuture<List<Set<String>>> combinedFutures = Futures.allAsList(list);

    // The get on the combined ListenableFuture will now block until 
    // ALL the individual threads have completed work.
    List<Set<String>> tableSets = combinedFutures.get();

    // Now all we have to do is combine the individual sets into a
    // single result
    Set<String> userList = new HashSet<String>();
    for (Set<String> tableSet: tableSets) {
        userList.addAll(tableSet);
    }

    return userList;
}

Executors和Futures的使用都是Java的核心。番石榴唯一要做的就是让我将Future变成ListenableFutures。请参阅此处以讨论为何后者更好。

可能仍有改善这种方法并行性的方法,但是如果您花费大量时间等待数据库响应或处理网络流量,则此方法可能会有所帮助。



 类似资料:
  • 我在Jenkins中配置了一个多分支管道项目。该项目在我的所有功能分支(git)上联调运行。对于管道项目中的每个作业,它都会创建一个我的webapp实例(启动tomcat和其他依赖项)。由于端口绑定问题,这会导致许多工作中断。 我可以限制多分支管道项目中的构建,以便每个功能分支的作业顺序运行而不是并行运行吗? 或者有没有更优雅的解决方案? 编辑:情况和问题: 我想在Jenkins中有一个多分支管道

  • 问题内容: 我们有一个基于石英的调度程序应用程序,该应用程序每分钟运行约1000个作业,每分钟的秒数均匀分布,即每秒约16-17个作业。理想情况下,这16-17个作业应同时触发,但是该作业的execute方法的第一个语句(仅记录执行时间)非常晚。例如,假设我们从05:00到05:04每分钟安排1000个作业。因此,理想情况下,计划在05:03:50进行的作业应该在05:03:50记录了execut

  • 问题内容: 我有以下方法: 在这里,我依次调用三种方法,这依次命中数据库并获取我的结果,然后对从数据库命中获得的结果进行后处理。我知道如何通过使用并发调用这三种方法。但是我想用Java 8 来实现。有人可以指导我如何通过并行流实现相同目标吗? 编辑 我只想通过Stream并行调用方法。 问题答案: 您可以利用这种方式:

  • 我有访问MySQL(5.7)数据库Wicket(8.6)应用程序。在spring-context.xml中建立mysql连接,如下所示: 我遇到的问题是,我需要执行一个非常长的SQL查询,根据所选的时间范围,这可能很容易花费几分钟的时间。我已经解释过,当执行查询时,整个wicket应用程序会减慢到这样的程度,即不再执行其他查询。顺便说一句:长查询只是一个读取查询。所以它不应该锁定一个表。br>如果

  • 我们有一个基于quartz的调度程序应用程序,每分钟运行大约1000个作业,这些作业平均分布在每分钟的几秒钟内,即每秒大约16-17个作业。理想情况下,这16-17个作业应该同时触发,但是我们的第一条语句,它只是记录执行的时间,任务的execute方法调用得很晚。假设从05:00到05:04,我们每分钟安排1000个工作。因此,理想情况下,计划在05:03:50的作业应该在05:03:50记录ex

  • 所以我有一个方法,返回一个完整的未来。在返回之前,该方法添加了一个带有accept的块,该块在CompletableFuture完成后执行。 此方法的调用者还添加了另一个块,其中包含