ArangoDB 3.1 查询解释器
ArangoDB 3.1 Query Explainer
当对索引数据库执行 AQL 时,我发现我的查询速度明显加快。但是,查询解释器指出没有使用索引。怎么会这样?这是一个错误吗?我 运行 在两个相同的数据库中进行相同的查询,只是一个有多种索引,另一个没有索引。在索引数据库中,查询需要 5 秒。在非索引数据库中,查询需要 13 秒。两个数据库都说在解释查询时没有使用索引,并提供相同的执行计划和优化规则。
查询:
let lastYear = left(date_subtract(date_now(),1,"year"),10)
for v0, e0, in outbound 'myFleet' graph 'myGraph'
filter e0.type == 'myType' && v0.attr == 'myAttr'
let myCount = (
for v1, e1 in outbound v0._id graph 'myOtherGraph'
filter e1.category == "myCategory" && e1.date > lastYear
collect with count into stuff
return stuff)
sort myCount desc
return {profile: v0.name, count: mycount[0]}
Execution plan:
Id NodeType Est. Comment
1 SingletonNode 1 * ROOT
2 CalculationNode 1 - LET lastYear = LEFT(DATE_SUBTRACT(DATE_NOW(), 1, "year"), 10) /* v8 expression */
3 TraversalNode 3 - FOR v0 /* vertex */, e0 /* edge */ IN 1..1 /* min..maxPathDepth */ OUTBOUND 'myFleet' /* startnode */ GRAPH 'myGraph'
4 CalculationNode 3 - LET #11 = (((e0.`type` == "myType") && (v0.`attr` == "myAttr"))) /* simple expression */
5 FilterNode 3 - FILTER #11
15 SubqueryNode 3 - LET myCount = ... /* subquery */
6 SingletonNode 1 * ROOT
7 CalculationNode 1 - LET #13 = v0.`_id` /* attribute expression */
8 TraversalNode 10 - FOR v1 /* vertex */, e1 /* edge */ IN 1..1 /* min..maxPathDepth */ OUTBOUND #13 /* startnode */ GRAPH 'myOtherGraph'
9 CalculationNode 10 - LET #17 = (e1.`category` == "myCategory") /* simple expression */
10 FilterNode 10 - FILTER #17
11 CalculationNode 10 - LET #19 = (e1.`date` > lastYear) /* simple expression */
12 FilterNode 10 - FILTER #19
13 CollectNode 1 - COLLECT WITH COUNT INTO stuff /* sorted*/
14 ReturnNode 1 - RETURN stuff
16 SortNode 3 - SORT myCount DESC
17 CalculationNode 3 - LET #21 = { "profile" : v0.`name`, "count" : myCount[0] } /* simple expression */
18 ReturnNode 3 - RETURN #21
指数
在索引数据库中:
v0.attr
具有:{hash: {unique: false, sparse: false}}
选择性 0.08%
e1.category
有 {hash: {unique: false, sparse: false}}
,选择性为 0.00%
e1.date
有 {skiplist: {unique: false, sparse: false}}
在非索引数据库中,唯一的索引是文档键和边缘标识符的默认值。
在索引数据库中,查询速度明显快于非索引数据库,但两者的查询解释器都说:
Indexes used:
none
很明显数据库正在使用索引,但查询解释器不会说明如何使用。
(注意:由于问题相似,所以给出了相同的答案here)
在 ArangoDB 3.0 中,遍历将始终使用边索引来查找连接的顶点,无论查询中存在哪些过滤条件,也无论存在哪些索引。
在 ArangoDB 3.1 中,优化器将尝试为每个遍历级别找到最佳索引。它将检查遍历的过滤条件,并为每个级别选择它估计成本最低的索引。如果没有用户定义的索引,它仍然会使用边索引来查找连接的顶点。如果边缘属性也被索引并且索引具有比边缘索引更好的估计平均选择性,则将使用其他索引。
在 3.1.0 中,遍历的解释输出将始终显示 "Indexes used: none",即使遍历将始终使用索引。解释输出中只是缺少索引显示。这已在 ArangoDB 3.1.1 中修复,它将显示优化器为每个遍历级别选择的单独索引。
例如,以下查询在 3.1 中显示以下解释输出:
Query string:
FOR v, e, p in 0..3 ANY 'v/test0' e
FILTER p.edges[0].type == 1 && p.edges[2].type == 2
RETURN p.vertices
Execution plan:
Id NodeType Est. Comment
1 SingletonNode 1 * ROOT
2 TraversalNode 8000 - FOR v /* vertex */, p /* paths */ IN 0..3 /* min..maxPathDepth */ ANY 'v/test0' /* startnode */ e
3 CalculationNode 8000 - LET #5 = ((p.`edges`[0].`type` == 1) && (p.`edges`[2].`type` == 2)) /* simple expression */
4 FilterNode 8000 - FILTER #5
5 CalculationNode 8000 - LET #7 = p.`vertices` /* attribute expression */
6 ReturnNode 8000 - RETURN #7
Indexes used:
By Type Collection Unique Sparse Selectivity Fields Ranges
2 edge e false false 10.00 % [ `_from`, `_to` ] base INBOUND
2 edge e false false 10.00 % [ `_from`, `_to` ] base OUTBOUND
2 hash e false false 63.60 % [ `_to`, `type` ] level 0 INBOUND
2 hash e false false 64.40 % [ `_from`, `type` ] level 0 OUTBOUND
2 hash e false false 63.60 % [ `_to`, `type` ] level 2 INBOUND
2 hash e false false 64.40 % [ `_from`, `type` ] level 2 OUTBOUND
[ "_to", "type" ]
和 [ "_from", "type" ]
上存在其他索引。那些在遍历的级别 0 和 2 上使用,因为在这些级别上存在可以使用这些索引的边的过滤条件。对于所有其他级别,遍历将使用 "Ranges" 列中标有 "base" 的索引。
即将发布的 3.1.1 将提供解释输出修复。
当对索引数据库执行 AQL 时,我发现我的查询速度明显加快。但是,查询解释器指出没有使用索引。怎么会这样?这是一个错误吗?我 运行 在两个相同的数据库中进行相同的查询,只是一个有多种索引,另一个没有索引。在索引数据库中,查询需要 5 秒。在非索引数据库中,查询需要 13 秒。两个数据库都说在解释查询时没有使用索引,并提供相同的执行计划和优化规则。
查询:
let lastYear = left(date_subtract(date_now(),1,"year"),10)
for v0, e0, in outbound 'myFleet' graph 'myGraph'
filter e0.type == 'myType' && v0.attr == 'myAttr'
let myCount = (
for v1, e1 in outbound v0._id graph 'myOtherGraph'
filter e1.category == "myCategory" && e1.date > lastYear
collect with count into stuff
return stuff)
sort myCount desc
return {profile: v0.name, count: mycount[0]}
Execution plan:
Id NodeType Est. Comment
1 SingletonNode 1 * ROOT
2 CalculationNode 1 - LET lastYear = LEFT(DATE_SUBTRACT(DATE_NOW(), 1, "year"), 10) /* v8 expression */
3 TraversalNode 3 - FOR v0 /* vertex */, e0 /* edge */ IN 1..1 /* min..maxPathDepth */ OUTBOUND 'myFleet' /* startnode */ GRAPH 'myGraph'
4 CalculationNode 3 - LET #11 = (((e0.`type` == "myType") && (v0.`attr` == "myAttr"))) /* simple expression */
5 FilterNode 3 - FILTER #11
15 SubqueryNode 3 - LET myCount = ... /* subquery */
6 SingletonNode 1 * ROOT
7 CalculationNode 1 - LET #13 = v0.`_id` /* attribute expression */
8 TraversalNode 10 - FOR v1 /* vertex */, e1 /* edge */ IN 1..1 /* min..maxPathDepth */ OUTBOUND #13 /* startnode */ GRAPH 'myOtherGraph'
9 CalculationNode 10 - LET #17 = (e1.`category` == "myCategory") /* simple expression */
10 FilterNode 10 - FILTER #17
11 CalculationNode 10 - LET #19 = (e1.`date` > lastYear) /* simple expression */
12 FilterNode 10 - FILTER #19
13 CollectNode 1 - COLLECT WITH COUNT INTO stuff /* sorted*/
14 ReturnNode 1 - RETURN stuff
16 SortNode 3 - SORT myCount DESC
17 CalculationNode 3 - LET #21 = { "profile" : v0.`name`, "count" : myCount[0] } /* simple expression */
18 ReturnNode 3 - RETURN #21
指数
在索引数据库中:
v0.attr
具有:{hash: {unique: false, sparse: false}}
选择性 0.08%e1.category
有{hash: {unique: false, sparse: false}}
,选择性为 0.00%e1.date
有{skiplist: {unique: false, sparse: false}}
在非索引数据库中,唯一的索引是文档键和边缘标识符的默认值。
在索引数据库中,查询速度明显快于非索引数据库,但两者的查询解释器都说:
Indexes used:
none
很明显数据库正在使用索引,但查询解释器不会说明如何使用。
(注意:由于问题相似,所以给出了相同的答案here)
在 ArangoDB 3.0 中,遍历将始终使用边索引来查找连接的顶点,无论查询中存在哪些过滤条件,也无论存在哪些索引。
在 ArangoDB 3.1 中,优化器将尝试为每个遍历级别找到最佳索引。它将检查遍历的过滤条件,并为每个级别选择它估计成本最低的索引。如果没有用户定义的索引,它仍然会使用边索引来查找连接的顶点。如果边缘属性也被索引并且索引具有比边缘索引更好的估计平均选择性,则将使用其他索引。
在 3.1.0 中,遍历的解释输出将始终显示 "Indexes used: none",即使遍历将始终使用索引。解释输出中只是缺少索引显示。这已在 ArangoDB 3.1.1 中修复,它将显示优化器为每个遍历级别选择的单独索引。
例如,以下查询在 3.1 中显示以下解释输出:
Query string:
FOR v, e, p in 0..3 ANY 'v/test0' e
FILTER p.edges[0].type == 1 && p.edges[2].type == 2
RETURN p.vertices
Execution plan:
Id NodeType Est. Comment
1 SingletonNode 1 * ROOT
2 TraversalNode 8000 - FOR v /* vertex */, p /* paths */ IN 0..3 /* min..maxPathDepth */ ANY 'v/test0' /* startnode */ e
3 CalculationNode 8000 - LET #5 = ((p.`edges`[0].`type` == 1) && (p.`edges`[2].`type` == 2)) /* simple expression */
4 FilterNode 8000 - FILTER #5
5 CalculationNode 8000 - LET #7 = p.`vertices` /* attribute expression */
6 ReturnNode 8000 - RETURN #7
Indexes used:
By Type Collection Unique Sparse Selectivity Fields Ranges
2 edge e false false 10.00 % [ `_from`, `_to` ] base INBOUND
2 edge e false false 10.00 % [ `_from`, `_to` ] base OUTBOUND
2 hash e false false 63.60 % [ `_to`, `type` ] level 0 INBOUND
2 hash e false false 64.40 % [ `_from`, `type` ] level 0 OUTBOUND
2 hash e false false 63.60 % [ `_to`, `type` ] level 2 INBOUND
2 hash e false false 64.40 % [ `_from`, `type` ] level 2 OUTBOUND
[ "_to", "type" ]
和 [ "_from", "type" ]
上存在其他索引。那些在遍历的级别 0 和 2 上使用,因为在这些级别上存在可以使用这些索引的边的过滤条件。对于所有其他级别,遍历将使用 "Ranges" 列中标有 "base" 的索引。
即将发布的 3.1.1 将提供解释输出修复。