Java ApacheGeode-连接上的查询性能

Java ApacheGeode-连接上的查询性能,java,spring-data,geode,Java,Spring Data,Geode,我使用ApacheGeode作为缓存解决方案。我需要在两个不同的区域内存储数据,并通过简单的连接查询检索它们 我尝试了复制区域和分区区域,但发现查询需要很长时间才能返回结果。我也在这两个区域添加了索引,这提高了性能,但仍然不够快。是否有人可以帮助改进此查询的性能 这是我试过的 示例1-分区区域 从缓存中检索大约7300条记录需要36秒 cache.xml中的配置 <region name="Department"> <region-attributes>

我使用ApacheGeode作为缓存解决方案。我需要在两个不同的区域内存储数据,并通过简单的连接查询检索它们

我尝试了复制区域和分区区域,但发现查询需要很长时间才能返回结果。我也在这两个区域添加了索引,这提高了性能,但仍然不够快。是否有人可以帮助改进此查询的性能

这是我试过的

示例1-分区区域

从缓存中检索大约7300条记录需要36秒

cache.xml中的配置

<region name="Department">
    <region-attributes>
        <partition-attributes redundant-copies="1">
        </partition-attributes>
    </region-attributes>
    <index name="deptIndex" from-clause="/Department" expression="deptId"/>
</region>

<region name="Employee">
    <region-attributes>
        <partition-attributes redundant-copies="1" colocated-with="Department">
        </partition-attributes>
    </region-attributes>
    <index name="empIndex" from-clause="/Employee" expression="deptId"/>
</region>
<region name="Department">
    <region-attributes refid="REPLICATE">
    </region-attributes>
    <index name="deptIndex" from-clause="/Department" expression="deptId"/>
</region>

<region name="Employee">
    <region-attributes refid="REPLICATE">
    </region-attributes>
    <index name="empIndex" from-clause="/Employee" expression="deptId"/>
</region>
执行功能

@Override
public void execute(FunctionContext context) {
// TODO Auto-generated method stub
Cache cache = CacheFactory.getAnyInstance();
QueryService queryService = cache.getQueryService();

ArrayList arguments = (ArrayList)context.getArguments();
String queryStr = (String)arguments.get(0);

Query query = queryService.newQuery(queryStr);

try {
    SelectResults result = (SelectResults)query.execute((RegionFunctionContext)context);

    ArrayList arrayResult = (ArrayList)result.asList();
    context.getResultSender().sendResult(arrayResult);
    context.getResultSender().lastResult(null);
} catch (FunctionDomainException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (TypeMismatchException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (NameResolutionException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (QueryInvocationTargetException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

}
Function function = new QueryFunction();
String queryStr = "SELECT * FROM /Department d, /Employee e WHERE d.deptId=e.deptId";
ArrayList argList = new ArrayList();
argList.add(queryStr);
Object result = FunctionService.onRegion(CacheFactory.getAnyInstance().getRegion("Department")).withArgs(argList).execute(function).getResult();

ArrayList resultList = (ArrayList)result;
ArrayList<StructImpl> finalList = (ArrayList)resultList.get(0);

你能描述一下你的域对象吗?员工和部门区域的关键和价值观是什么?你在用PDX吗

一个简单的方法是将
deptId
作为部门区域的键。然后,在函数中,您只需迭代
员工
区域,并在
部门
区域上执行
get(deptId)
。为了进一步减少延迟,您可以在服务器继续运行该功能的同时将一大块结果发送回客户端。由于您提到结果中有7000多个条目,因此可以从服务器一次批处理500个条目。大概是这样的:

@Override
public void execute(FunctionContext context) {
  RegionFunctionContext rfc = (RegionFunctionContext) context;
  Region<EmpId, PDXInstance> employee = PartitionRegionHelper.getLocalPrimaryData(rfc.getDataSet());
  Region<DeptId, PDXInstance> department = PartitionRegionHelper.getLocalPrimaryData(rfc.getDataSet());
  int count = 0;
  Map<PdxInstance, PdxInstance> results = new HashMap<>();
  for (Region.Entry<EmpId, PDXInstance> e : employee.entrySet()) {
    PdxInstance dept = department.get(e.getValue().get("deptId"));
    results.put(e.getValue(), dept);
    if (count == 500) {
      context.getResultSender().sendResult(results);
      results.clear();
      count = 0;
    }
  }
  context.getResultSender().lastResult(results);
}
@覆盖
public void execute(FunctionContext){
RegionFunctionContext rfc=(RegionFunctionContext)上下文;
Region employee=PartitionRegionHelper.getLocalPrimaryData(rfc.getDataSet());
Region department=PartitionRegionHelper.getLocalPrimaryData(rfc.getDataSet());
整数计数=0;
映射结果=新的HashMap();
对于(Region.Entry e:employee.entrySet()){
PdxInstance dept=department.get(例如getValue().get(“deptId”);
结果.put(e.getValue(),dept);
如果(计数=500){
context.getResultSender().sendResult(结果);
结果:清晰();
计数=0;
}
}
context.getResultSender().lastResult(结果);
}

然后,在客户机上,您可以使用一个自定义程序,该程序将能够在结果从服务器到达时逐块处理这些结果。

我尝试过的上述结果使用java序列化。我将其改为使用PDX,结果要快得多。使用PDX复制的区域的结果现在是470毫秒。所以序列化看起来确实对性能有很大的影响。我的Employee对象上的键是empId,我的Department对象上的键是deptId,我在Employee和Department中都在deptId上创建了索引。我还能做些什么来提高性能吗?有没有其他序列化方法可以提供更好的结果?我的评论太大,无法放在这里,所以最后编辑了我的原始答案。
@Override
public void execute(FunctionContext context) {
  RegionFunctionContext rfc = (RegionFunctionContext) context;
  Region<EmpId, PDXInstance> employee = PartitionRegionHelper.getLocalPrimaryData(rfc.getDataSet());
  Region<DeptId, PDXInstance> department = PartitionRegionHelper.getLocalPrimaryData(rfc.getDataSet());
  int count = 0;
  Map<PdxInstance, PdxInstance> results = new HashMap<>();
  for (Region.Entry<EmpId, PDXInstance> e : employee.entrySet()) {
    PdxInstance dept = department.get(e.getValue().get("deptId"));
    results.put(e.getValue(), dept);
    if (count == 500) {
      context.getResultSender().sendResult(results);
      results.clear();
      count = 0;
    }
  }
  context.getResultSender().lastResult(results);
}