适用于:
小鬼
本文概述了如何使用 Azure Cosmos DB for Gremlin 图形数据库的执行概要步骤。 此步骤提供有关故障排除和查询优化的相关信息,并与可针对 Cosmos DB Gremlin API 帐户执行的任何 Gremlin 查询兼容。
若要使用此步骤,只需在 executionProfile()
Gremlin 查询末尾追加函数调用。
将执行 Gremlin 查询 ,作的结果将返回包含查询执行配置文件的 JSON 响应对象。
例如:
// Basic traversal
g.V('mary').out()
// Basic traversal with execution profile call
g.V('mary').out().executionProfile()
调用 executionProfile()
该步骤后,响应将是一个 JSON 对象,其中包括执行的 Gremlin 步骤、所花费的总时间,以及语句生成的 Cosmos DB 运行时运算符的数组。
注释
Apache Tinkerpop 规范中不定义执行概况的实现。 它特定于用于 Gremlin 实现的 Azure Cosmos DB。
响应示例
下面是将返回的输出的批注示例:
注释
此示例使用注释来解释回复的一般结构。 实际的 executionProfile 响应不会包含任何注释。
[
{
// The Gremlin statement that was executed.
"gremlin": "g.V('mary').out().executionProfile()",
// Amount of time in milliseconds that the entire operation took.
"totalTime": 28,
// An array containing metrics for each of the steps that were executed.
// Each Gremlin step will translate to one or more of these steps.
// This list is sorted in order of execution.
"metrics": [
{
// This operation obtains a set of Vertex objects.
// The metrics include: time, percentTime of total execution time, resultCount,
// fanoutFactor, count, size (in bytes) and time.
"name": "GetVertices",
"time": 24,
"annotations": {
"percentTime": 85.71
},
"counts": {
"resultCount": 2
},
"storeOps": [
{
"fanoutFactor": 1,
"count": 2,
"size": 696,
"time": 0.4
}
]
},
{
// This operation obtains a set of Edge objects.
// Depending on the query, these might be directly adjacent to a set of vertices,
// or separate, in the case of an E() query.
//
// The metrics include: time, percentTime of total execution time, resultCount,
// fanoutFactor, count, size (in bytes) and time.
"name": "GetEdges",
"time": 4,
"annotations": {
"percentTime": 14.29
},
"counts": {
"resultCount": 1
},
"storeOps": [
{
"fanoutFactor": 1,
"count": 1,
"size": 419,
"time": 0.67
}
]
},
{
// This operation obtains the vertices that a set of edges point at.
// The metrics include: time, percentTime of total execution time and resultCount.
"name": "GetNeighborVertices",
"time": 0,
"annotations": {
"percentTime": 0
},
"counts": {
"resultCount": 1
}
},
{
// This operation represents the serialization and preparation for a result from
// the preceding graph operations. The metrics include: time, percentTime of total
// execution time and resultCount.
"name": "ProjectOperator",
"time": 0,
"annotations": {
"percentTime": 0
},
"counts": {
"resultCount": 1
}
}
]
}
]
注释
executionProfile 步骤将执行 Gremlin 查询。 这包括addV
或addE
步骤,这将导致结果的创建,并提交查询中指定的更改。 因此,Gremlin 查询生成的请求单位也将被收费。
执行配置文件响应对象
executionProfile() 函数的响应将生成具有以下结构的 JSON 对象的层次结构:
Gremlin操作对象:表示已执行的整个 Gremlin操作。 包含以下属性。
-
gremlin
:已执行的显式 Gremlin 语句。 -
totalTime
:执行步骤所用时间(以毫秒为单位)。 -
metrics
:一个数组,其中包含执行以完成查询的每个 Cosmos DB 运行时运算符。 此列表按执行顺序排序。
-
Cosmos DB 运行时运算符:表示整个 Gremlin 操作的每个组件。 此列表按执行顺序排序。 每个对象包含以下属性:
-
name
:运算符的名称。 这是被评估和执行的那种步骤。 在下表中阅读详细信息。 -
time
:给定运算符花费的时间(以毫秒为单位)。 -
annotations
:包含特定于已执行的运算符的其他信息。 -
annotations.percentTime
:执行特定运算符所花费的总时间的百分比。 -
counts
:此运算符从存储层返回的对象数。 这在counts.resultCount
标量值内包含。 -
storeOps
:表示可以跨越一个或多个分区的存储操作。 -
storeOps.fanoutFactor
:表示此特定存储操作访问的分区数。 -
storeOps.count
:表示此存储作返回的结果数。 -
storeOps.size
:表示给定存储作结果的大小(以字节为单位)。
-
Cosmos DB Gremlin 运行时运算符 | Description |
---|---|
GetVertices |
此步骤从持久性层获取一组谓词对象。 |
GetEdges |
此步骤获取与一组顶点相邻的边缘。 此步骤可能会导致一个或多个存储操作。 |
GetNeighborVertices |
此步骤获取连接到一组边缘的顶点。 边缘包含其源顶点和目标顶点的分区键和 ID。 |
Coalesce |
此步骤用于在执行 coalesce() Gremlin 步骤时评估两个操作。 |
CartesianProductOperator |
此步骤计算两个数据集之间的笛卡尔积。 通常在使用谓词to() 或from() 时执行。 |
ConstantSourceOperator |
此步骤计算表达式以生成常量值作为结果。 |
ProjectOperator |
此步骤使用上述操作的结果来准备和序列化响应。 |
ProjectAggregation |
此步骤准备并序列化集合操作的响应。 |
注释
随着新运算符的添加,此列表会继续更新。
有关如何分析执行剖面响应的示例
下面是可以使用执行配置文件响应发现的常见优化示例:
- 盲人扇出查询。
- 未筛选的查询。
盲扇出查询模式
假设以下执行配置文件响应来自分区的图:
[
{
"gremlin": "g.V('tt0093640').executionProfile()",
"totalTime": 46,
"metrics": [
{
"name": "GetVertices",
"time": 46,
"annotations": {
"percentTime": 100
},
"counts": {
"resultCount": 1
},
"storeOps": [
{
"fanoutFactor": 5,
"count": 1,
"size": 589,
"time": 75.61
}
]
},
{
"name": "ProjectOperator",
"time": 0,
"annotations": {
"percentTime": 0
},
"counts": {
"resultCount": 1
}
}
]
}
]
可以从中得出以下结论:
- 查询是单个 ID 查找,因为 Gremlin 语句遵循模式
g.V('id')
。 -
time
从指标来看,此查询的延迟似乎很高,因为单个点读操作的延迟超过 10 毫秒。 - 如果查看对象
storeOps
,可以看到该fanoutFactor
对象是5
,这意味着此作访问了 5 个分区 。
作为此分析的结论,我们可以确定第一个查询访问了超过必要的分区。 可以通过将查询中的分区键指定为谓词来解决此问题。 这会导致延迟减少,每个查询的成本也更少。 详细了解 图形分区。 更理想的查询是 g.V('tt0093640').has('partitionKey', 't1001')
。
未筛选的查询模式
比较以下两个执行概要结果。 为简单起见,这些示例使用单个分区图形。
此第一个查询使用标签 tweet
检索所有顶点,然后获取其相邻顶点:
[
{
"gremlin": "g.V().hasLabel('tweet').out().executionProfile()",
"totalTime": 42,
"metrics": [
{
"name": "GetVertices",
"time": 31,
"annotations": {
"percentTime": 73.81
},
"counts": {
"resultCount": 30
},
"storeOps": [
{
"fanoutFactor": 1,
"count": 13,
"size": 6819,
"time": 1.02
}
]
},
{
"name": "GetEdges",
"time": 6,
"annotations": {
"percentTime": 14.29
},
"counts": {
"resultCount": 18
},
"storeOps": [
{
"fanoutFactor": 1,
"count": 20,
"size": 7950,
"time": 1.98
}
]
},
{
"name": "GetNeighborVertices",
"time": 5,
"annotations": {
"percentTime": 11.9
},
"counts": {
"resultCount": 20
},
"storeOps": [
{
"fanoutFactor": 1,
"count": 4,
"size": 1070,
"time": 1.19
}
]
},
{
"name": "ProjectOperator",
"time": 0,
"annotations": {
"percentTime": 0
},
"counts": {
"resultCount": 20
}
}
]
}
]
请注意同一查询的性能分析,但现在有一个附加筛选器 has('lang', 'en')
,再浏览相邻顶点:
[
{
"gremlin": "g.V().hasLabel('tweet').has('lang', 'en').out().executionProfile()",
"totalTime": 14,
"metrics": [
{
"name": "GetVertices",
"time": 14,
"annotations": {
"percentTime": 58.33
},
"counts": {
"resultCount": 11
},
"storeOps": [
{
"fanoutFactor": 1,
"count": 11,
"size": 4807,
"time": 1.27
}
]
},
{
"name": "GetEdges",
"time": 5,
"annotations": {
"percentTime": 20.83
},
"counts": {
"resultCount": 18
},
"storeOps": [
{
"fanoutFactor": 1,
"count": 18,
"size": 7159,
"time": 1.7
}
]
},
{
"name": "GetNeighborVertices",
"time": 5,
"annotations": {
"percentTime": 20.83
},
"counts": {
"resultCount": 18
},
"storeOps": [
{
"fanoutFactor": 1,
"count": 4,
"size": 1070,
"time": 1.01
}
]
},
{
"name": "ProjectOperator",
"time": 0,
"annotations": {
"percentTime": 0
},
"counts": {
"resultCount": 18
}
}
]
}
]
但是,这两个查询达到了相同的结果,但第一个查询需要更多请求单位,因为它需要在查询相邻项之前循环访问更大的初始数据集。 在比较两个响应中的以下参数时,我们可以看到此行为的指示器:
- 在第
metrics[0].time
个响应中,数值较高,这表示这一步骤耗费了更长的时间才能完成。 - 该值
metrics[0].counts.resultsCount
在第一个响应中也更高,指示初始工作数据集更大。
后续步骤
- 了解 Azure Cosmos DB 中 支持的 Gremlin 功能 。
- 详细了解 Azure Cosmos DB 中的 Gremlin API。