【问题标题】:Slow query response time - simple friends of friends cypher query查询响应时间慢 - 好友密码查询的简单好友
【发布时间】:2019-02-02 09:11:53
【问题描述】:

我正在使用 NEO4j 3.5 来存储和查询人与人之间的关系。我有标签为“用户”的节点和标签为“朋友”的关系。我能够得到朋友的朋友,但查询时间太长。它目前在 4 秒到 6 秒内返回。这不是一个高事务性 neo4j 数据库,服务器有大量可用的 CPU 和内存。服务器上的负载低于 3,并且有 8 个核心。这是在 AWS EC2 实例上运行的。数据库中大约有 250,000 个节点,数据库总大小在 750mb 以下。

这是我目前使用的查询:

MATCH (user:User {user_id:1145})-[:FRIENDS*3]->(fof:User)
WHERE NOT (user:User)-[:FRIENDS]->(fof:User)
RETURN count(distinct fof.user_id)

此密码查询返回的计数为 69,704,这是正确的。

可以对 cypher 查询或 NEO4j 数据库引擎进行哪些优化以更快地返回结果?

执行计划

+-----------------------+----------------+--------+---------+-----------+-----------------------------+------------------+--------------------------------------------+
| Operator              | Estimated Rows | Rows   | DB Hits | Cache H/M | Identifiers                 | Ordered by       | Other                                      |
+-----------------------+----------------+--------+---------+-----------+-----------------------------+------------------+--------------------------------------------+
| +ProduceResults       |              0 |      1 |       0 |       0/0 | count(distinct fof.user_id) |                  | 0.0                                        |
| |                     +----------------+--------+---------+-----------+-----------------------------+------------------+--------------------------------------------+
| +EagerAggregation     |              0 |      1 |  326421 |       0/0 | count(distinct fof.user_id) |                  | 0.0                                        |
| |                     +----------------+--------+---------+-----------+-----------------------------+------------------+--------------------------------------------+
| +AntiSemiApply        |              0 | 256717 |       0 |       0/0 | anon[33], fof, user         | user.user_id ASC | 0.0                                        |
| |\                    +----------------+--------+---------+-----------+-----------------------------+------------------+--------------------------------------------+
| | +Expand(Into)       |              0 |      0 | 8006149 |       0/0 |   REL80, fof, user          |                  | 0.0; (user)-[  REL80:FRIENDS]->(fof)       |
| | |                   +----------------+--------+---------+-----------+-----------------------------+------------------+--------------------------------------------+
| | +Filter             |              1 | 260120 |  520240 |       0/0 | fof, user                   |                  | 0.0; fof:User                              |
| | |                   +----------------+--------+---------+-----------+-----------------------------+------------------+--------------------------------------------+
| | +Argument           |              1 | 260120 |       0 |       0/0 | fof, user                   |                  | 0.0                                        |
| |                     +----------------+--------+---------+-----------+-----------------------------+------------------+--------------------------------------------+
| +Filter               |              0 | 260120 |  260120 |       0/0 | anon[33], fof, user         | user.user_id ASC | 0.0; fof:User                              |
| |                     +----------------+--------+---------+-----------+-----------------------------+------------------+--------------------------------------------+
| +VarLengthExpand(All) |              0 | 260120 |  267999 |       0/0 | anon[33], fof, user         | user.user_id ASC | 0.0; (user)-[anon[33]:FRIENDS*3..3]->(fof) |
| |                     +----------------+--------+---------+-----------+-----------------------------+------------------+--------------------------------------------+
| +NodeIndexSeek        |              1 |      1 |       3 |       0/0 | user                        | user.user_id ASC | 0.0; :User(user_id)                        |
+-----------------------+----------------+--------+---------+-----------+-----------------------------+------------------+--------------------------------------------+

【问题讨论】:

  • 请记住,:FRIENDS*3 不是朋友的朋友,而是朋友的朋友。

标签: neo4j cypher


【解决方案1】:
  1. 您的WHERE 子句包含一个模式,该模式需要每个fof 的额外数据库命中。您可以通过在内存中保存user 的所有直接朋友的列表并更改您的WHERE 子句使其仅在列表中搜索来避免这些数据库命中。 (根据您的个人资料数据,这可以节省 8006149+520240 或超过 850 万次数据库命中 - 这是您整个查询的大部分命中。)

  2. 在您的查询中,如果多次匹配相同的fof 节点,则每次都会执行相同的WHERE 测试。您可以通过在执行WHERE 测试之前过滤掉重复的fof 节点 来避免这种情况。这也意味着您以后不再需要删除重复项。

例如:

MATCH (user:User {user_id:1145})-[:FRIENDS]->(f:User)
WITH user, COLLECT(f) AS friends
MATCH (user)-[:FRIENDS*3]->(fof:User)
WITH DISTINCT friends, fof
WHERE NOT fof IN friends
RETURN COUNT(fof)

【讨论】:

    猜你喜欢
    • 2015-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多