首页 > 编程知识 正文

大数据查询怎么优化,sqlserver大数据量查询优化

时间:2023-05-03 13:52:17 阅读:222128 作者:4212

问题描述:涉及到大数据量,多循环查询的时候,往往查询的速度会变慢,影响系统的使用性能。该问题,在测试环境尚不明显,因为测试环境的数据量毕竟是有限的。

但是,一旦将代码更新到线上的真实系统,因为数据量一下子增大,会造成数据查询的缓慢,所造成的严重迟滞,就不能被忽略了。

业务场景:云计算系统。底层会将采集过来的宿主机流量数据,进行保存。后台管理系统,需要定时计算从底层传递过来的宿主机的带宽的总体实际使用量,并且用实际使用量,除以节点的总带宽,得到相关的出网、入网的带宽使用率。


方案分析:
1.在保存数据的时候,事实计算出数据使用量,后续查询时,通过sql语句的sum方法直接汇总。
2.开启多线程并发查询。


一、利用Callable多线程,实现查询优化的例子

原理同一个Callable的简单例子。核心在于运用多线程,创建带有返回值的查询。

1.准备查询参数

2.根据每页数据量,去判断应该创建的线程的数量。

3.根据数据的总数量,平均分配每个线程处理的数量。

4.将查询返回的Future,保存在list中(注意,这样做可以提升查询速度,先批量保存结果,再处理的方式,要快于拿到值就处理的方式)

5.        latch.await();

6.遍历List,数据处理+分页,返回数据值。

public String services(){List <Future<Map<String,Object>>> list=new ArrayList<Future<Map<String,Object>>>();int total=0;//1.准备需要传递的参数String condition = dealContent();List<CompanyEntity> companyList = companyService.list(condition, -1, -1);List<Node> nodeList = new ArrayList<Node>();int nodeId = getNodeId();if(nodeId != 0){Node node = nodeService.getById(nodeId);nodeList.add(node);}else{nodeList = nodeService.getAll();}List<JSONObject> comList = new ArrayList<JSONObject>();for(CompanyEntity company : companyList){for(Node node : nodeList){JSONObject jsonObj = new JSONObject();jsonObj.put("companyName", company.getCompanyName());jsonObj.put("companyId", company.getCompanyId());jsonObj.put("companyType", company.getType());jsonObj.put("nodeName",node.getNode_name());jsonObj.put("nodeId",node.getNode_id());jsonObj.put("nodeIp", node.getNode_ip());comList.add(jsonObj);}}//2.数据分页处理int pagesize=Integer.parseInt(super.getPagesize());int nopage=Integer.parseInt(super.getNowpage());int ThrearNum=0;if(pagesize>ThreadUtil.CORE_POOL_SIZE){ThrearNum=ThreadUtil.CORE_POOL_SIZE;}else{ThrearNum=pagesize;}try {//计算数据总量:int sumDataCount=comList.size();List<JSONObject> dataList=new ArrayList<JSONObject>();final CountDownLatch latch = new CountDownLatch(ThrearNum);boolean flag=false;int dataEnd=0;int addData=0;int j=1;for (int i = 0; i < ThrearNum; i++) {List<JSONObject> addList=new ArrayList<JSONObject>();List<JSONObject> tempList=new ArrayList<JSONObject>(comList.size());tempList=comList;List<JSONObject> dealList=new ArrayList<JSONObject>();if(sumDataCount%ThrearNum!=0){addData=sumDataCount%ThrearNum;flag=true;}//计算每个线程要处理的数据总量:int dataCountPerThread=sumDataCount/ThrearNum;//计算当前线程数据处理的起始索引:int dataStart=i*dataCountPerThread;//计算当前线程数据处理的结束索引:dataEnd=(i+1)*dataCountPerThread;//截取List,作为当前线程所需要处理的全部数据:if(flag){if(j<=addData){//多余的数据,从最后的索引开始平均分配addList.add(tempList.get(tempList.size()-j));j++;}dealList=subData(tempList,dataStart, dataEnd);if(addList.size()!=0){dealList.add(addList.get(0));addList.remove(0);}}else{dealList=subData(tempList,dataStart, dataEnd);//如果这里不使用subData,而是使用subList,则会报错:java.util.ConcurrentModificationException//dealList=comList.subList(dataStart, dataEnd);}Callable<Map<String,Object>> c1 = new CallableCountThread(condition,dealList,VpcFlag,slbFlag,blockFlag,vpnFlag,latch);Future<Map<String,Object>> f1=pool.submit(c1);list.add(f1);}latch.await();for(int i=0;i<list.size();i++){Future<Map<String,Object>> f1=list.get(i);total+=(Integer)f1.get().get("count");if(null!=f1.get().get("data")){dataList.addAll((List<JSONObject>)f1.get().get("data"));}}doPage_special(total);//3.查询分页开始和结束的索引位int nowpage2 = (Integer) dataMap.get("nowpage"); int pagesize2 = (Integer) dataMap.get("pagesize");List<JSONObject> showData=new ArrayList<JSONObject>();if(dataList.size()==0){}else{if(nopage==1){if(dataList.size()<=pagesize2){showData=dataList.subList(0,dataList.size()-1);showData.add(dataList.get(dataList.size()-1));}else{showData=dataList.subList(0,pagesize2);}}else{if(dataList.size()<=(nopage)*pagesize2){showData=dataList.subList((nopage-1)*pagesize2,dataList.size()-1);showData.add(dataList.get(dataList.size()-1));}else{showData=dataList.subList((nopage-1)*pagesize2,nopage*pagesize2);}}}generateSuccessListResponse(showData);} catch (InterruptedException | ExecutionException e) {// TODO Auto-generated catch blocke.printStackTrace();}return JSON;}

二、查询效率

没有使用duox多线程:

 

查询时间在16s左右

 

使用多线程查询:

查询时间在1.7s左右

 

查询速度提升了十倍。

 

三、心得总结:

1.写代码的时候,不能仅仅只考虑功能的实现。特别是涉及到数据量比较大的时候,任何一次查询的精简,带来的效率提升都是显著的。

2.多线程在具体场景中的使用是非常重要的。在涉及到返回值的时候,就需要使用到Callable接口。

3.任何时候,写完代码,都要自己给自己做code review。回过头去看看自己写的代码。能不能优化,能不能再优化。

 

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。