探索查询执行摘要
在来自查询的所有结果都已处理后,服务器通过返回执行摘要来结束事务。它以 ResultSummary
对象的形式出现,其中包含以下信息
检索执行摘要
当使用 Driver.execute_query()
运行查询时,执行摘要是默认返回对象的一部分,位于 summary
键下。
records, result_summary, keys = driver.execute_query("""
UNWIND ["Alice", "Bob"] AS name
MERGE (p:Person {name: name})
""", database_="neo4j",
)
# or result_summary = driver.execute_query('<QUERY>').summary
如果您使用的是 事务函数,或使用 Driver.execute_query()
使用 自定义转换器,则可以使用 Result.consume()
方法检索查询执行摘要。请注意,一旦您请求执行摘要,结果流就会耗尽。这意味着任何尚未处理的记录将不再可用。
def create_people(tx):
result = tx.run("""
UNWIND ["Alice", "Bob"] AS name
MERGE (p:Person {name: name})
""")
return result.consume()
with driver.session(database="neo4j") as session:
result_summary = session.execute_write(create_people)
查询计数器
属性 ResultSummary.counters
包含查询触发的操作的计数器(作为 SummaryCounters
对象)。
summary = driver.execute_query("""
MERGE (p:Person {name: $name})
MERGE (p)-[:KNOWS]->(:Person {name: $friend})
""", name="Mark", friend="Bob",
database_="neo4j",
).summary
print(summary.counters)
"""
{'_contains_updates': True, 'labels_added': 2, 'relationships_created': 1,
'nodes_created': 2, 'properties_set': 2}
"""
还有两个充当元计数器的附加布尔属性
-
contains_updates
— 查询是否触发了在其运行的数据库上的任何写入操作 -
contains_system_updates
— 查询是否更新了system
数据库
查询执行计划
如果您在查询前加上 EXPLAIN
,服务器将返回它将用于运行查询的计划,但不会实际运行它。然后,该计划在属性 ResultSummary.plan
下可用,并包含将用于检索结果集的 Cypher 运算符 列表。您可以使用此信息来查找潜在的瓶颈或性能改进的空间(例如,通过创建索引)。
_, summary, _ = driver.execute_query("EXPLAIN MATCH (p {name: $name}) RETURN p", name="Alice")
print(summary.plan['args']['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
下可用。请注意,查询也会运行,因此结果对象还包含任何结果记录。
records, summary, _ = driver.execute_query("PROFILE MATCH (p {name: $name}) RETURN p", name="Alice")
print(summary.profile['args']['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.summary_notifications
包含 SummaryNotification
对象的列表。
records, summary, keys = driver.execute_query("""
MATCH p=shortestPath((:Person {name: 'Alice'})-[*]->(:Person {name: 'Bob'}))
RETURN p
""", database_="neo4j"
)
"""
[SummaryNotification(
title='The provided pattern is unbounded, consider adding an upper limit to the number of node hops.',
code='Neo.ClientNotification.Statement.UnboundedVariableLengthPattern',
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_level=<NotificationSeverity.INFORMATION: 'INFORMATION'>,
category=<NotificationCategory.PERFORMANCE: 'PERFORMANCE'>,
raw_severity_level='INFORMATION',
raw_category='PERFORMANCE',
position=SummaryNotificationPosition(line=1, column=22, offset=21)
)]
"""
在版本 >= 5.25 中,属性 ResultSummary.gql_status_objects
包含 GqlStatusObject
的序列。这些是符合 GQL 的状态对象。
一些(但不是全部)GqlStatusObjects
是通知,而一些报告结果状态:00000
表示“成功”,02000
表示“无数据”,00001
表示“省略结果”。ResultSummary.gql_status_objects
始终至少包含一个条目,其中包含结果状态。
records, summary, keys = driver.execute_query("""
MATCH p=shortestPath((:Person {name: 'Alice'})-[*]->(:Person {name: 'Bob'}))
RETURN p
""", database_="neo4j"
)
for status in summary.gql_status_objects:
print("GQLSTATUS:", status.gql_status)
print("Description:", status.status_description)
# Not all statuses are notifications.
print("Is notification:", status.is_notification)
# Notification and thus vendor-specific fields.
# These fields are only meaningful for notifications.
if status.is_notification:
# The position in the query that caused the notification.
print("Position:", status.position)
# The notification's classification is counterpart to `neo4j.NotificationCategory`.
# However, the term `category` has a different meaning in the context of GQL.
print("Classification:", status.classification)
print("Unparsed classification:", status.raw_classification)
print("Severity:", status.severity)
print("Unparsed severity:", status.raw_severity)
# Any raw extra information provided by the DBMS:
print("Diagnostic record:", status.diagnostic_record)
print("=" * 80)
"""
GQLSTATUS: 02000
Description: note: no data
Is notification: False
Diagnostic record: {'OPERATION': '', 'OPERATION_CODE': '0', 'CURRENT_SCHEMA': '/'}
================================================================================
GQLSTATUS: 03N91
Description: 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.
Is notification: True
Position: line: 1, column: 22, offset: 21
Classification: NotificationClassification.PERFORMANCE
Unparsed classification: PERFORMANCE
Severity: NotificationSeverity.INFORMATION
Unparsed severity: INFORMATION
Diagnostic record: {'_classification': 'PERFORMANCE', '_status_parameters': {'pat': "(:Person {name: 'Alice'})-[*]->(:Person {name: 'Bob'})"}, '_severity': 'INFORMATION', '_position': {'offset': 21, 'line': 1, 'column': 22}, 'OPERATION': '', 'OPERATION_CODE': '0', 'CURRENT_SCHEMA': '/'}
================================================================================
"""
过滤通知
默认情况下,服务器会针对所有类别和严重程度的通知分析每个查询。从版本 5.7 开始,您可以使用参数 notifications_min_severity
和/或 notifications_disabled_categories
/notifications_disabled_classifications
来限制您感兴趣的通知的严重程度和/或类别/分类。限制服务器允许引发的通知数量会略微提高性能。
严重程度过滤器适用于 Neo4j 和 GQL 通知。类别和分类过滤器仅由于 GQL 和 Neo4j 之间的词汇差异而单独存在;但是,这两个过滤器都会影响任何形式的通知,因此您应该只使用其中一个。如果您同时提供类别和分类过滤器,则其内容将合并。您可以在创建 Driver
实例时或创建会话时使用任何这些参数。
您可以通过将最小严重程度设置为 'OFF'
来完全禁用通知。
WARNING
通知,但不允许 HINT
或 GENERIC
类别的通知# at driver level
driver = neo4j.GraphDatabase.driver(
URI, auth=AUTH,
notifications_min_severity='WARNING', # or 'OFF' to disable entirely
notifications_disabled_classifications=['HINT', 'GENERIC'], # filters categories as well
)
# at session level
session = driver.session(
database="neo4j",
notifications_min_severity='INFORMATION', # or 'OFF' to disable entirely
notifications_disabled_classifications=['HINT'] # filters categories as well
)