我有以下映射数据库行条目的 pojo:
public class Pojo{
//key
private String a;
private String b;
private String c;
//other columns
private String d;
private String e;
private String f;
//defining attributes on each field with capital letter (ex: a->A)
}
我创建了以下集合:
IndexedCollection<Pojo> cq = new ConcurrentIndexedCollection<Pojo>();
//...loading data in collection from DB...
cq.addIndex(NavigableIndex.onAttribute(Pojo.A)); //part of key in DB
cq.addIndex(NavigableIndex.onAttribute(Pojo.F)); //not part of key in DB
最后,我根据从数据库(所有表)中获取的 200k 元素来衡量以下查询的性能:
Query<Pojo> query1 = and(equal(Pojo.A, par1),
equal(Pojo.F, par2));
当然等价于:
select* where A=? and F=?
但我的索引策略(其中我为查询的每个参数定义一个索引)似乎缺少一些东西,因为与直接数据库访问相比,我的查询仅将处理速度提高了 7 毫秒。将所有表格都放在内存中,我希望有更好的性能......我做错了什么?
最佳答案
我是 CQEngine 的作者,所以我希望这对您有所帮助。由于索引的配置方式,您可能遇到了过多的过滤。
假设您有一组 Car 对象,每个对象都有一个 COLOR
属性和 MANUFACTURER
属性。
如果在 COLOR
上添加索引,以及关于 MANUFACTURER
的单独索引,那么 CQEngine 将能够快速检索到 'blue' 汽车集,或者能够快速检索到 'Ford' 汽车集。 (..到目前为止一切顺利..)
但是,如果您尝试检索'blue' 和 'Ford' 制造的汽车(即复杂的 and()
查询),则您不再寻找“蓝色” 汽车组或“福特” 汽车组 - 您需要这些组的交集 .
所以在这种情况下,CQEngine 会发现没有可以返回交集的单个索引。索引次优。
使用次优索引评估查询
为了回答查询,CQEngine 将使用来自两个可用索引的统计信息来确定两个子查询中的哪一个匹配最少的汽车。也就是说,哪个集合更小:“蓝色” 汽车集合,还是“福特” 汽车集合?
假设集合中有 100 万辆汽车。其中,假设有 10 万辆汽车是蓝色的,而 9 万辆汽车是由福特制造的。
CQEngine 将通过从 MANUFACTURER
上的索引中检索 90K 'Ford' 汽车来回答查询,并对 9 万辆汽车中的每一辆进行过滤,以确定它是否也是“蓝色”汽车。
很可能该系列中只有 5K 辆汽车都是“蓝色”并且由“福特”制造。但由于索引不是响应此类请求的最佳选择,因此将扫描和过滤 90,000 辆汽车。
注意:我已经简化了这个示例,因为在实践中,大多数过滤都是惰性的,并且会被避免,因为应用程序不太可能在单个请求中请求然后循环访问数千辆蓝色福特汽车。
避免过滤
如果您需要减少查询的延迟,则需要考虑避免上述过滤的方法。
所以在这种情况下,您可以考虑添加一个 CompoundIndex
在 A 和 F 上,而不是两个单独的索引。
关于java - 如何正确索引查询条件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41702068/