Медленное время ответа на запрос - простой шифр запроса друзей друзей - PullRequest
0 голосов
/ 01 февраля 2019

Я использую NEO4j 3.5 для хранения и запроса отношений между людьми.У меня есть узлы с меткой «Пользователь» и связи с меткой «Друзья».Я могу найти друзей друзей, но запрос занимает слишком много времени.В настоящее время возвращается через 4 с до 6 с.Это не высокопроизводительная транзакционная база данных neo4j, и на сервере достаточно ресурсов ЦП и памяти.Нагрузка на сервер меньше 3, а ядер 8.Это работает на экземпляре AWS EC2.В базе данных приблизительно 250 000 узлов, а общий размер базы данных составляет менее 750 МБ.

Вот запрос, который я сейчас использую:

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, что правильно.

Какие оптимизации могут быть внесены либо в запрос на шифрование, либо в механизм базы данных 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)                        |
+-----------------------+----------------+--------+---------+-----------+-----------------------------+------------------+--------------------------------------------+

1 Ответ

0 голосов
/ 01 февраля 2019
  1. Ваше предложение WHERE содержит шаблон, который требует дополнительных обращений к БД на fof.Вы можете избежать этих обращений к БД, сохранив в памяти список всех ближайших друзей user и изменив предложение WHERE так, чтобы оно просто осуществляло поиск в списке.(Согласно данным вашего профиля это может сэкономить 8006149 + 520240 или более 8,5 миллионов обращений к БД, что составляет большинство обращений для всего вашего запроса.)

  2. В вашем запросе, если один и тот же узел fof сопоставляется несколько раз, каждый раз будет выполняться один и тот же тест WHERE.Вы можете избежать этого, отфильтровывая дубликаты fof узлов перед тем, как выполнит тест WHERE.Это также означает, что вам больше не нужно удалять дубликаты позже.

Например:

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...