【问题标题】:Neo4j paginated query optimizationNeo4j 分页查询优化
【发布时间】:2023-02-15 11:16:38
【问题描述】:

我有两个查询,一个是通常编写分页查询的方式

MATCH (e:Event), (e)--(l:Place), (e)--(u:User)
OPTIONAL MATCH (e)--(ls:LiveStream)
WITH e {
  .*,
  _id: id(e),
  location: properties(l),
  livestream: properties(ls),
  photos: [(e)--(p:Photo) | p.url],
  createdAt: toString(e.createdAt),
  tags: [(e)--(t:Tag) | properties(t)]
} AS event
RETURN event
SKIP $page * $size
LIMIT $size

下一个在 Event 节点上使用早期的 SKIPLIMIT

MATCH (e:Event)
WITH e SKIP $page * $size LIMIT $size
MATCH (e)--(l:Place), (e)--(u:User)
OPTIONAL MATCH (e)--(ls:LiveStream)
WITH e {
  .*,
  _id: id(e),
  location: properties(l),
  livestream: properties(ls),
  photos: [(e)--(p:Photo) | p.url],
  createdAt: toString(e.createdAt),
  tags: [(e)--(t:Tag) | properties(t)]
} AS event
RETURN event

使用 SKIP 值为 0 和 LIMIT 为 10,第一个的查询规划器产生

而第二个产量的查询计划器

第一个似乎遍历整个数据库,而第二个只从 10 个Event 节点开始。

两者的优缺点是什么,尤其是随着数据库中数据量的增加。

【问题讨论】:

    标签: database optimization neo4j cypher query-optimization


    【解决方案1】:

    第二个查询:

    MATCH (e:Event)
    WITH e SKIP $page * $size LIMIT $size
    MATCH (e)--(l:Place), (e)--(u:User)
    OPTIONAL MATCH (e)--(ls:LiveStream)
    WITH e {
      .*,
      _id: id(e),
      location: properties(l),
      livestream: properties(ls),
      photos: [(e)--(p:Photo) | p.url],
      createdAt: toString(e.createdAt),
      tags: [(e)--(t:Tag) | properties(t)]
    } AS event
    RETURN event
    

    是首选方式,因为它只遍历 10 个事件节点的关系,无论是链接到 Place、User、Photo 还是 Tag。因此,此查询遍历的图非常小。这里唯一需要注意的是,您使用MATCH 来查找与PlaceUser 的链接。因此,如果 10 个事件节点中的任何一个未链接到任何 PlaceUser。它会被过滤掉。

    第一个查询遍历所有事件节点的关系,然后分页,这使得大量图形遍历和数据转换操作无用。因此它的性能不高。

    随着图形大小的增加,第二个查询是可行的方法。另外,我注意到你没有在任何地方使用 User 节点,所以你可能想删除它,如果它们是多余的。

    【讨论】:

    • 感谢您的回答。我的直觉认为那会更好,但我需要确认(正是那些聪明的技巧让你最终成功)。保证始终有 PlaceUser 链接到任何事件。为了简洁起见,我删除了返回结果的某些方面。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多