我有以下pojo,它映射了一个db行条目:
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
最后,我根据从db(所有表)中取出的 200k 元素来衡量以下查询的性能:
Query<Pojo> query1 = and(equal(Pojo.A, par1),
equal(Pojo.F, par2));
当然,相当于:
select* where A=? and F=?
但似乎我的索引策略,其中我为查询的每个参数定义索引,缺少一些东西,因为我的查询仅比直接数据库访问仅仅7毫秒处理。把所有的表放在记忆中我会期待一些更好的表现......我做错了什么?
答案 0 :(得分:4)
我是CQEngine的作者,所以我希望这会有所帮助。由于索引的配置方式,您可能会遇到过多的过滤。
假设您有一组Car对象,每个对象都有COLOR
属性和MANUFACTURER
属性。
如果您在COLOR
上添加索引,在MANUFACTURER
上添加单独的索引,则CQEngine将能够检索&#39; blue&#39; 汽车很快,或者它能够快速检索出&#39; Ford&#39; 汽车。 (..太好了..)
但是,如果您尝试检索由&#39; Ford&#39; 制造的&#39; blue&#39; AND的汽车(即,一个复杂的and()
查询),那么你不是在寻找一套&#39; 汽车或一套&#39; Ford&#39 ; 汽车了 - 您需要集合的交叉点。
所以在这种情况下,CQEngine会发现没有一个索引可以返回交集。索引次优。
使用次优索引评估查询
要回答查询,CQEngine将使用两个可用索引中的统计信息来确定两个子查询中的哪一个与最少的汽车匹配。也就是说,哪一套较小:&#39; 汽车的集合,或&#39;福特&#39; 汽车的集合?< / p>
让我们说这个系列中有100万辆汽车。其中,我们说100K汽车是蓝色的,90K汽车是由福特生产的。
CQEngine将通过MANUFACTURER
上的索引检索90K &#39; Ford&#39; 汽车来回答查询,并过滤每辆90K汽车以确定它是否是还有&#39; blue&#39; 。
很可能该系列中只有5K汽车&#39; blue&#39; 并由&#39; Ford&#39; 。但由于索引不是最佳的回答这样的请求,因此将扫描和过滤90K汽车。
注意:我已经简化了这个例子,因为在实践中,大多数过滤都是懒惰的,并且避免了,因为应用程序不太可能请求,然后在单个中迭代数千辆蓝色福特汽车请求。
避免过滤
如果您需要减少查询的延迟,则需要考虑避免可能发生的过滤的方法。
因此,在这种情况下,您可以考虑在A和F上添加单个CompoundIndex
,而不是两个单独的索引。