如何正确索引查询条件?
How to correctly index where conditions of a query?
我有以下映射数据库行条目的 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 个元素(所有 table)测量了以下查询的性能:
Query<Pojo> query1 = and(equal(Pojo.A, par1),
equal(Pojo.F, par2));
当然等同于:
select* where A=? and F=?
但我的索引策略(我在其中为查询的每个参数定义一个索引)似乎缺少一些东西,因为与直接数据库访问相比,我的查询仅将处理速度提高了 7 毫秒。在内存中拥有所有 table 我希望有更好的表现......我做错了什么?
我是 CQEngine 的作者,希望对您有所帮助。由于索引的配置方式,您可能遇到了过多的过滤。
假设您有一个 Car 对象集合,每个对象都有一个 COLOR
属性和一个 MANUFACTURER
属性。
如果您在 COLOR
上添加一个索引,并在 MANUFACTURER
上添加一个单独的索引,那么 CQEngine 将能够检索 'blue'[= 的集合63=]辆很快,否则它就能很快地检索出'Ford'辆汽车的集合。 (..到目前为止一切顺利..)
但是,如果您尝试检索 'blue' 且由 'Ford' 制造的汽车(也就是说,一个复杂的 and()
查询),那么您不是在寻找 'blue' 汽车的集合或 [=82 的集合=] 汽车了 - 你需要 交叉路口 的集合。
所以在这种情况下,CQEngine会发现没有一个索引可以return交集。指标次优。
使用次优索引评估查询
为了回答查询,CQEngine 将使用来自两个可用索引的统计信息来确定两个子查询中的哪一个匹配最少的汽车。也就是说,哪个集合更小:'blue'辆汽车的集合,还是'Ford'辆汽车的集合?
假设集合中有 100 万辆汽车。其中,假设 10 万辆汽车是蓝色的,9 万辆汽车是福特制造的。
CQEngine 将通过从 MANUFACTURER
上的索引中检索 90K 'Ford' 辆汽车来回答查询,并过滤这 90K 辆汽车中的每一辆以确定是否它也是 'blue'.
很可能该系列中只有 5000 辆汽车都是 'blue' 并且由 'Ford' 制造.但由于索引不是响应此类请求的最佳选择,因此将扫描和过滤 90,000 辆汽车。
注意:我已经简化了这个例子,因为在实践中,大部分过滤都是惰性的,并且避免了,因为应用程序不太可能请求然后迭代数以千计的蓝色福特汽车单个请求。
避免过滤
如果您需要减少查询的延迟,则需要考虑避免上述过滤的方法。
所以在这种情况下,您可以考虑在 A 和 F 上添加一个 CompoundIndex
,而不是两个单独的索引。
我有以下映射数据库行条目的 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 个元素(所有 table)测量了以下查询的性能:
Query<Pojo> query1 = and(equal(Pojo.A, par1),
equal(Pojo.F, par2));
当然等同于:
select* where A=? and F=?
但我的索引策略(我在其中为查询的每个参数定义一个索引)似乎缺少一些东西,因为与直接数据库访问相比,我的查询仅将处理速度提高了 7 毫秒。在内存中拥有所有 table 我希望有更好的表现......我做错了什么?
我是 CQEngine 的作者,希望对您有所帮助。由于索引的配置方式,您可能遇到了过多的过滤。
假设您有一个 Car 对象集合,每个对象都有一个 COLOR
属性和一个 MANUFACTURER
属性。
如果您在 COLOR
上添加一个索引,并在 MANUFACTURER
上添加一个单独的索引,那么 CQEngine 将能够检索 'blue'[= 的集合63=]辆很快,否则它就能很快地检索出'Ford'辆汽车的集合。 (..到目前为止一切顺利..)
但是,如果您尝试检索 'blue' 且由 'Ford' 制造的汽车(也就是说,一个复杂的 and()
查询),那么您不是在寻找 'blue' 汽车的集合或 [=82 的集合=] 汽车了 - 你需要 交叉路口 的集合。
所以在这种情况下,CQEngine会发现没有一个索引可以return交集。指标次优。
使用次优索引评估查询
为了回答查询,CQEngine 将使用来自两个可用索引的统计信息来确定两个子查询中的哪一个匹配最少的汽车。也就是说,哪个集合更小:'blue'辆汽车的集合,还是'Ford'辆汽车的集合?
假设集合中有 100 万辆汽车。其中,假设 10 万辆汽车是蓝色的,9 万辆汽车是福特制造的。
CQEngine 将通过从 MANUFACTURER
上的索引中检索 90K 'Ford' 辆汽车来回答查询,并过滤这 90K 辆汽车中的每一辆以确定是否它也是 'blue'.
很可能该系列中只有 5000 辆汽车都是 'blue' 并且由 'Ford' 制造.但由于索引不是响应此类请求的最佳选择,因此将扫描和过滤 90,000 辆汽车。
注意:我已经简化了这个例子,因为在实践中,大部分过滤都是惰性的,并且避免了,因为应用程序不太可能请求然后迭代数以千计的蓝色福特汽车单个请求。
避免过滤
如果您需要减少查询的延迟,则需要考虑避免上述过滤的方法。
所以在这种情况下,您可以考虑在 A 和 F 上添加一个 CompoundIndex
,而不是两个单独的索引。