一次针对批量查询处理的优化

2019-03-27 01:05|来源: 网路

    客户调用批量查询接口对Solr核进行查询时觉得查询响应时间有些慢,接口的内部实现目前是顺序执行每个查询,再把结果汇总起来返回给调用方。因此,考虑引入线程池对查询接口的内部实现进行重构优化。

       先声明一个大小可随之增长的线程池,

private ExecutorService executor = Executors.newCachedThreadPool(); // 查询请求处理线程池

     然后是主线程方法的代码:

     public List<Map<String, String>> queryEntityList(String entityCode, List<Long> idList) throws ServiceException {

        List<Map<String, String>> finalResult =  null;
         if (idList ==  null || idList.size() == 0 || StringUtil.isBlank(entityCode)) { // 参数合法性校验
             return finalResult;
        }
        finalResult =  new ArrayList<Map<String, String>>();
        
        List<Future<Map<String, String>>> futureList =  new ArrayList<Future<Map<String, String>>>();
         int threadNum = idList.size(); // 查询子线程数目
         for ( int i = 0; i < threadNum; i++) {
            Long itemId = idList.get(i);
            Future<Map<String, String>> future = executor.submit( new QueryCallable (entityCode, itemId));
            futureList.add(future);
        }
         for(Future<Map<String, String>> future : futureList) {
            Map<String, String> threadResult =  null;
             try {
                threadResult = future.get();
            }  catch (Exception e) { 
                threadResult =  null;
            }
             if ( null != threadResult && threadResult.size() > 0) { // 结果集不为空
                finalResult.add(threadResult);
            }
        }
         return finalResult;
    }
    最后是具体负责处理每个查询请求的 Callable
public  class QueryCallable  implements Callable<Map<String, String>> {
         private String entityCode = "";
         private Long itemId = 0L;
        
         public GetEntityListCallable(String entityCode, Long itemId) {
             this. entityCode = entityCode;
             this.itemId = itemId;
        }
         public Map<String, String> call()  throws Exception {
            Map<String, String> entityMap =  null;
             try {
                entityMap = QueryServiceImpl. this.getEntity(entityCode, itemId); // 先去hbase查基本信息

            }  catch (Exception e) {
                entityMap =  null;
            }
             return entityMap;
        }
    }

        通过线程池的使用,可以减少创建,销毁进程所带来的系统开销,而且线程池中的工作线程可以重复使用,极大地利用现有系统资源,增加了系统吞吐量。

另外,今天也尝试了另一种合并Solr索引的方法,直接通过底层的Lucene的API进行,而不是提交Http请求,具体方法如下:

java -cp lucene-core-3.4.0.jar:lucene-misc-3.4.0.jar org/apache/lucene/misc/IndexMergeTool ./newindex ./app1/solr/data/index ./app2/solr/data/index 


转自:http://www.cnblogs.com/phinecos/archive/2011/12/29/2306775

相关问答

更多
  • 启几个线程并行来查,最后把结果集合并。
  • MySQL查询优化[2022-07-13]

    select product_id, sum(stock_amount) as stock_amount, sum(stock_branch) as stock_branch from stock_details where product_id in(很多,但是一般不会超过1000) group by product_id 我不是很建议用 where product_id in(很多,但是一般不会超过1000) 这种的方式,这样速度会比较慢,如果考虑到优化一般都会用 where (表A.Product_I ...
  • 在我们使用MySQL数据库时,比较常用也是查询,包括基本查询,关联查询,条件查询等等,对于同一个操作,SQL语句的实现有很多种写法,但是不同的写法查询的性能可能会有很大的差异。这里主要介绍下select查询优化的要点。 1. 使用慢查询日志去发现慢查询。 2. 使用执行计划去判断查询是否正常运行。 3. 总是去测试你的查询看看是否他们运行在最佳状态下 –久而久之性能总会变化。 4. 避免在整个表上使用count(*),它可能锁住整张表。 5. 使查询保持一致以便后续相似的查询可以使用查询缓存。 6. 在适当 ...
  • 像你说的,sql没有什么优化的可能了。 只能从数据库技术上面来优化,使用并行、提升io吞吐量、启用压缩、使用分区将表分片存放在不同硬盘上(如果没有使用raid的话)。 有些可疑,你可以进一步判断一下,是数据库这边查询比较慢,还是应用程序层处理起来比较慢。
  • 不知道你的关联方式 再一个,10W多不算太多 关联的相关字段建立相应的索引 where条件的字段也建立相应的索引 其实也就这样 主要是看你那语句怎么写,才能确定建立什么样的索引
  • 那就一条一条的写不就行了啊,一条一条的执行呗
  • 使用OUTER APPLY SELECT fn.id, oa.rid, oa.gid FROM finding fn OUTER apply (SELECT TOP 1 s.rid, f.gid FROM find f JOIN status s ...
  • 好吧,不能解决这个问题,但是在石英作业中实现它,使其并发,并部署5个vms并在一天内完成该过程。 蛮力。 Well, can´t get fixed this, but implemented it in a quartz job,made it concurrent, and deployed 5 vms and get the process done in a day. Brute force.
  • DELETE FROM t1 USING t1 JOIN t2 ON t1.key = t2.key LIMIT 1000; 并重复,直到没有剩余,这允许长时间不阻止表。 UPD:但是如果你需要加入同一个表,这个解决方案将不起作用。 UPD2:我忽略了NOT ,这是更正的查询: DELETE FROM t1 USING t1 LEFT JOIN t2 ON t1.key = t2.key WHERE t2.key IS NULL LIMIT 1000; 我应该注意,这是子查询以与JOIN相同的速度执行的 ...
  • 因此,经过多次改进后,我们已经改变了我们的方法,以实现我们所需的吞吐量。 事实证明,我们只关注它们在那里的100,000个记录/秒,并且它们用于更新连续滚动的聚合和实时值集。 我们使用大量工作线程将100,000行批量插入到临时堆表中(因此使用4个工作线程,每个线程处理大约25,000行),然后将聚簇索引应用于临时表。 然后,我们将临时表中的数据直接合并到实时和聚合表中,并删除临时表。 这里我们使用ROWLOCK提示强制SQL采用ROWLOCK而不是TABLOCK或PAGLOCK,这会导致工作线程之间的争用 ...