探索查询执行摘要
处理完查询的所有结果后,服务器通过返回执行摘要来结束事务。它以 ResultSummary
对象的形式提供,并包含以下信息:
检索执行摘要
使用 Driver.executeQuery()
运行查询时,执行摘要是默认返回对象的一部分,位于 summary
属性下。
let { records, summary } = await driver.executeQuery(`
UNWIND ['Alice', 'Bob'] AS name
MERGE (p:Person {name: name})
`, {},
{ database: 'neo4j' }
)
// or summary = (await driver.executeQuery('<QUERY>')).summary
如果您使用 事务函数,如果您使用 await
来解析结果 Promise,可以通过属性 Result.summary
检索查询执行摘要;如果您将结果作为 Promise 消费,则可以通过方法 Result.summary()
检索。
请注意,一旦您请求执行摘要,结果流就会耗尽。这意味着任何尚未处理的记录都将被丢弃。
let session = driver.session({ database: 'neo4j' })
try {
let summary = await session.executeWrite(async tx => {
let result = await tx.run(`
UNWIND ['Alice', 'Bob'] AS name
MERGE (p:Person {name: name})
`)
return result.summary
// or result.summary(), if you don't await tx.run()
})
} finally {
session.close()
}
查询计数器
属性 ResultSummary.counters
包含查询触发的操作的计数器(作为一个 QueryStatistics
对象)。
let { records, summary } = await driver.executeQuery(`
UNWIND ['Alice', 'Bob'] AS name
MERGE (p:Person {name: name})
`, {},
{ database: 'neo4j' }
)
console.log(summary.counters.updates())
/*
{
nodesCreated: 2,
nodesDeleted: 0,
relationshipsCreated: 0,
relationshipsDeleted: 0,
propertiesSet: 0,
labelsAdded: 1,
labelsRemoved: 0,
indexesAdded: 0,
indexesRemoved: 0,
constraintsAdded: 0,
constraintsRemoved: 0
}
*/
console.log(summary.counters.containsUpdates()) // true
console.log(summary.counters.containsSystemUpdates()) // false
ResultSummary.counters
上还有两个额外的方法,它们充当元计数器
-
.containsUpdates()
— 查询是否在其运行的数据库上触发了任何写入操作 -
.containsSystemUpdates()
— 查询是否更新了system
数据库
查询执行计划
如果您在查询前加上 EXPLAIN
,服务器将返回它将用于运行查询的计划,但不会实际运行它。该计划随后作为 Plan
对象在属性 ResultSummary.plan
下可用,并包含用于检索结果集的 Cypher 运算符列表。您可以使用此信息来查找潜在的瓶颈或性能改进空间(例如通过创建索引)。
let result = await driver.executeQuery('EXPLAIN MATCH (p {name: $name}) RETURN p', { name: 'Alice' })
console.log(result.summary.plan.arguments['string-representation'])
/*
Planner COST
Runtime PIPELINED
Runtime version 5.0
Batch size 128
+-----------------+----------------+----------------+---------------------+
| Operator | Details | Estimated Rows | Pipeline |
+-----------------+----------------+----------------+---------------------+
| +ProduceResults | p | 1 | |
| | +----------------+----------------+ |
| +Filter | p.name = $name | 1 | |
| | +----------------+----------------+ |
| +AllNodesScan | p | 10 | Fused in Pipeline 0 |
+-----------------+----------------+----------------+---------------------+
Total database accesses: ?
*/
如果您改为在查询前加上关键字 PROFILE
,服务器将返回它已用于运行查询的执行计划,以及分析器统计信息。这包括使用的运算符列表以及每个中间步骤的额外分析信息。该计划在属性 ResultSummary.profile
下可用。请注意,查询也会运行,因此结果对象也包含任何结果记录。
let result = await driver.executeQuery('PROFILE MATCH (p {name: $name}) RETURN p', { name: 'Alice' })
console.log(result.summary.profile.arguments['string-representation'])
/*
Planner COST
Runtime PIPELINED
Runtime version 5.0
Batch size 128
+-----------------+----------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| Operator | Details | Estimated Rows | Rows | DB Hits | Memory (Bytes) | Page Cache Hits/Misses | Time (ms) | Pipeline |
+-----------------+----------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
| +ProduceResults | p | 1 | 1 | 3 | | | | |
| | +----------------+----------------+------+---------+----------------+ | | |
| +Filter | p.name = $name | 1 | 1 | 4 | | | | |
| | +----------------+----------------+------+---------+----------------+ | | |
| +AllNodesScan | p | 10 | 4 | 5 | 120 | 9160/0 | 108.923 | Fused in Pipeline 0 |
+-----------------+----------------+----------------+------+---------+----------------+------------------------+-----------+---------------------+
Total database accesses: 12, total allocated memory: 184
*/
有关更多信息和示例,请参阅 基本查询调优。
通知
执行查询后,服务器可以返回与查询结果一起的通知。通知包含性能改进建议、关于使用已弃用功能的警告以及关于 Neo4j 次优使用的其他提示。
对于驱动程序版本大于等于 5.25 和服务器版本大于等于 5.23,有两种形式的通知可用(Neo4j 状态码 和 GQL 状态码)。对于早期版本,仅有 Neo4j 状态码 可用。 GQL 状态码计划取代 Neo4j 状态码。 |
属性 ResultSummary.notifications
包含一个 Notification
对象列表。
let { records, summary } = await driver.executeQuery(`
MATCH p=shortestPath((:Person {name: 'Alice'})-[*]->(:Person {name: 'Bob'}))
RETURN p
`, {},
{ database: 'neo4j' }
)
console.log(summary.notifications)
/*
[
Notification {
code: 'Neo.ClientNotification.Statement.UnboundedVariableLengthPattern',
title: 'The provided pattern is unbounded, consider adding an upper limit to the number of node hops.',
description: 'Using shortest path with an unbounded pattern will likely result in long execution times. It is recommended to use an upper limit to the number of node hops in your pattern.',
severity: 'INFORMATION',
position: { offset: 24, line: 2, column: 22 },
severityLevel: 'INFORMATION',
rawSeverityLevel: 'INFORMATION',
category: 'PERFORMANCE',
rawCategory: 'PERFORMANCE'
}
]
*/
对于版本大于等于 5.25,属性 ResultSummary.gqlStatusObjects
包含一个 GqlStatusObject
对象列表。这些是符合 GQL 规范的状态对象。
部分(但非全部)GqlStatusObjects
是通知,而有些则报告一个结果状态:00000
表示“成功”,02000
表示“无数据”,00001
表示“省略结果”。Summary.GqlStatusObjects()
始终包含至少一个条目,其中包含结果状态。
let { records, summary } = await driver.executeQuery(`
MATCH p=shortestPath((:Person {name: 'Alice'})-[*]->(:Person {name: 'Bob'}))
RETURN p
`, {},
{ database: 'neo4j' }
)
console.log(summary.gqlStatusObjects)
/*
[
GqlStatusObject {
gqlStatus: '02000',
statusDescription: 'note: no data',
diagnosticRecord: { OPERATION: '', OPERATION_CODE: '0', CURRENT_SCHEMA: '/' },
position: undefined,
severity: 'UNKNOWN',
rawSeverity: undefined,
classification: 'UNKNOWN',
rawClassification: undefined,
isNotification: false
},
GqlStatusObject {
gqlStatus: '03N91',
statusDescription: "info: unbounded variable length pattern. The provided pattern `(:Person {name: 'Alice'})-[*]->(:Person {name: 'Bob'})` is unbounded. Shortest path with an unbounded pattern may result in long execution times. Use an upper limit (e.g. `[*..5]`) on the number of node hops in your pattern.",
diagnosticRecord: {
OPERATION: '',
OPERATION_CODE: '0',
CURRENT_SCHEMA: '/',
_classification: 'PERFORMANCE',
_status_parameters: [Object],
_severity: 'INFORMATION',
_position: [Object]
},
position: { offset: 24, line: 2, column: 24 },
severity: 'INFORMATION',
rawSeverity: 'INFORMATION',
classification: 'PERFORMANCE',
rawClassification: 'PERFORMANCE',
isNotification: true
}
]
*/
过滤通知
默认情况下,服务器会分析每个查询的所有类别和严重级别的通知。从版本 5.7 开始,您可以使用参数 minimumSeverityLevel
和/或 disabledCategories
/disabledClassifications
来限制您感兴趣的通知的严重级别和/或类别/分类。限制服务器允许生成的通知数量会略微提高性能。
严重级别过滤器适用于 Neo4j 和 GQL 通知。类别和分类过滤器仅因 GQL 和 Neo4j 之间的词汇差异而单独存在;不过,这两种过滤器都会影响任何形式的通知,因此您应该只使用其中一个。您可以在创建 Driver
实例或创建会话时使用这些参数中的任何一个。
您可以通过将最低严重级别设置为 'OFF'
来完全禁用通知。
WARNING
通知,但不允许 HINT
或 GENERIC
分类// at driver level
let driver = neo4j.driver(
URI, neo4j.auth.basic(USER, PASSWORD), {
notificationsFilter: {
minimumSeverityLevel: 'WARNING', // or 'OFF' to disable entirely
disabledClassifications: ['HINT', 'GENERIC'] // filters categories as well
}
}
)
// at session level
let session = driver.session({
database: 'neo4j',
notificationsFilter: {
minimumSeverityLevel: 'WARNING', // or 'OFF' to disable entirely
disabledClassifications: ['HINT', 'GENERIC'] // filters categories as well
}
})